477 Commits

Author SHA1 Message Date
lili
c77b0064be fix(ai): 修 AI 流 SSE 长任务候选丢失(后端死线可配≥上游+前端重连幂等)+A1 启动脚本固化 AI 凭据
studio e2e ai-generation 真红根因=SSE 协议/时序 bug:后端 SSE 死线 30s < LLM 真实时延(且<上游自己 180s 总窗口)+前端 connectAIStream 无重连→长 AI 生成候选永丢(ai-gen 真红/accept flaky 同此 bug)。按方案 A1+候选③(design-docs/临时-01)、人类 review 批准后执行。

A1 环境固化:start-muse-server-infra.sh 追加 source p1r-external-acceptance.env(仅 source 路径不硬编凭据、缺失告警不退出)。后端③死线可配:MuseAiTaskStreamServiceImpl 删 DEFAULT_TIMEOUT_MILLIS 硬编码、改 @Value muse.ai.sse.task-timeout-millis 默认 240000(≥上游 TOTAL_TIMEOUT 180s+轮询/回放余量),连接死线(:70)+poll deadline(:198)同引用;application.yaml 加配置项。前端③重连+幂等:sse.ts connectAIStream 非终态结束退避重连续 poll、按 SSE id 去重(后端每次 seq0 全量回放→lastSeenSequenceNo 丢弃已见)、done/error terminal 停、总超时 300s→onError 不静默卡死;返回 AbortController、AIPanel 零改动。

compatibility:connectAIStream 唯一调用方 AIPanel、streamTask 唯一入口 controller、events 模块 30s 死线独立不动;回滚 git checkout、无 DB 迁移。验证:后端 SSE 单测 14/14+前端 107/107(含 4 新重连去重用例)、活体 e2e ai-generation+accept 连跑 3 轮 6/6 全绿、DB 落 6 行真 LLM suggestion、重连幂等方法 A 活体证。残留:本机 LLM 6.8-19s 未自然跨 30s、慢路径靠 240s 数学覆盖+单测+重连活体证三重保证。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:51:41 -07:00
lili
09c35f5eee docs(ai-e2e): AI 流 SSE 长任务超时修复方案评审文档(待 review、不改 code)
studio e2e ai-generation 真红深诊出 SSE 协议/时序 code bug,按规范(产品行为变更先评审)出方案评审文档供 human review。两层根因:①server 启动漏 source acceptance env(AI 凭据)②后端 DEFAULT_TIMEOUT_MILLIS=30s 同时作 SSE 连接死线(:60)+poll deadline(:188)、< 上游自己 180s 总窗口(MUSE_AI_NEW_API_TOTAL_TIMEOUT_SECONDS),前端 connectAIStream 无重连(AIPanel 流结束不重连不报错)。

推荐 A1(启动脚本固化 AI 凭据)+候选③(后端放宽死线兜底+前端断连重连容错),排期紧分阶段 A1→①→②。3 决策点待 review:timeout 取值(应 ≥180s+余量、非初稿 120s)/是否上前端重连(推翻 AI 流一次性设计)/重连续传幂等候选去重。text+2 mermaid(因果时序+选项关系)+html 人读图;大纲注册 v7→v8。本轮未改 code、待 review 后执行。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:18:21 -07:00
lili
45ca6f4881 docs(ai-e2e): 回写 AI 真生成 e2e 真红深诊(两层根因:环境已修+SSE code bug 方案评审中)
进度总账加 AI e2e 诊断 entry:ai-generation 真红/accept flaky 深诊定位两层均非 AI 外部(New-API 在线)——①server 漏 source p1r-external-acceptance.env(已重启修、脚本待固化)②后端 SSE DEFAULT_TIMEOUT_MILLIS=30s 死线<LLM 时延(11-60s)+前端 connectAIStream 无重连(SSE 协议产品行为变更、用户选 A 方案评审中)。同步 knowledge bug entry 标已修闭环 0b152d9。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:11:29 -07:00
lili
0b152d9c6d fix(knowledge): 修 KB 绑 ≥2 作品停用/删除必 500 真后端 bug + 补真 PG IT(studio e2e 真连揪出)
studio e2e knowledge-disable-restore 真连揪出 mock 单测掩盖的生产 bug:任何用户把知识库绑到 ≥2 作品后无法停用/删除(disable POST HTTP 200 但 body code:500)。根因:updateStatusByKbId 给该 KB 所有未删 binding 写同一停用 commandId→违反 uk_muse_knowledge_binding_command(tenant_id,command_id)唯一索引→DuplicateKeyException。

command_id 语义=「创建/最后改写该 binding 的命令」行级幂等键(单行写路径 create/delete/updateInstalled 各写一行;对称 source projection 无 command_id、用 last_event_id 印证 KB 级 fan-out 不占行级幂等槽);KB 级停用是 KB 维度单命令(commandId 已记 muse_knowledge_base+source_event)、非 binding 创建命令。修(候选①传播不覆盖 command_id):updateStatusByKbId(Long,String,String)→(Long,String)删 setCommandId 只翻 binding_status;propagateKbBlocked 去 commandId 参传 sourceEventId;disableGlobalKnowledgeBase(:190)/changeUserStatus(:452 user disable+delete)2 调用点同步。

影响面=全局/用户 KB disable+用户 KB delete 三传播路径,行为变化仅不再改写 binding.command_id(binding_status/affectedBindings/source projection 不变);对外契约不变、纯修 500;回滚 git checkout。

mock 单测掩盖根因(mock updateStatusByKbId 返行数、不触发真唯一索引)。补真 PG IT P1rKnowledgeBaseDisableMultiBindingIT(真 PG+Flyway V14+真 service/mapper):KB 绑 2 作品 disable/delete 传播成功+两 binding 各保留 command_id;反假绿用例直写同 command_id 仍被唯一约束拒(SQLState 23505)。修后 3/3 绿;临时重引入 bug→2/3 DuplicateKeyException 证真回归门禁。独立核实:e2e 连跑 3 次 2 passed(修前红);psql 复核 KB1 2 binding(work1+work2)全 disabled、command_id 各异无冲突;global-setup 补 9b 多 binding 锚点(KB1+work2)令 e2e 真走 ≥2 binding 传播路径。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 18:20:50 -07:00
lili
d8badcde11 docs(studio-e2e): 回写 studio e2e 全量核查(健康 54/56)+前端双 bug 修+flaky 根治+真后端 bug 发现
studio e2e 核查里程碑:36 spec/56 case MSW-off 真连、整体健康 0 假绿候选。修前端双 bug(443a1f3 ChapterPanel 双提交+WorkspacePage 乐观锁兜底)、环境 fixture(de5f4d0 asset1/work1 复位)、来源污染 flaky(ca0e04c source-attribution 解耦 block3)。最大价值=揪出真后端 bug(knowledge updateStatusByKbId 多 binding 写同 commandId 违反 uk 唯一索引→KB 绑≥2 作品无法停用、mock 单测掩盖、用户批准委托修中)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:58:28 -07:00
lili
ca0e04c9a9 test(studio-e2e): source-attribution 解耦到 pristine block3 根治测试间来源污染 flaky
source-attribution 只读 spec 期望 block1 来源=user_original,但全量串行时前序 accept-suggestion(写 ai_suggestion)/block-autosave/block-structure 按字母序先跑且都写 block1,block1 顶层 revision 来源在 user_original/ai_suggestion 漂移→偶发渲染"AI 生成"红;global-setup 每轮仅跑一次、无法撤销跑中途污染。修:spec 改读 pristine work3/block3(grep 确认无人导航 /workspace/3、无人写 block3)+global-setup §3 每轮删净 block3 归因并重建唯一 user_original rev1 行(幂等)。断言未放宽仍真断言 user_original。免疫验证:强灌 block1 顶层 ai_suggestion(旧 spec 必红条件)新 spec 仍绿;独立连跑 source-attribution 3 次全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:35:19 -07:00
lili
de5f4d0bf9 test(studio-e2e): global-setup 补 asset1/work1 fixture 复位(环境污染致 7 spec 偶发红)
studio e2e 全量核查 run1 7 红,根因测试间环境污染、global-setup 复位不全:①asset1「活体市场资产·测试」被历史操作 delisted(应 listed/active)→bind-precheck 返 1044000003 资产不存在→连带 handoff-agent/content/knowledge+live-read 市场浏览+market-governance-impact+market-handoff-precheck 6 红;②work1 残留多余 writing.expansion active 槽位(spec 假设仅 continuation)→agent-slot-bind strict 命中 2 元素红。修:§17 复位 asset1→listed/active、§18 删 work1 非 continuation 槽位。验证:重新污染→自愈后 7 spec 全绿、全量回归持续绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:47:28 -07:00
lili
443a1f3414 fix(studio): 修新建章节双提交 + work 乐观锁版本兜底两处 bug(studio e2e 真连揪出)
studio e2e chapter-create-delete 偶发 code=1041000002,根因两个独立前端 bug:①ChapterPanel 双提交:input onKeyDown(Enter→submitCreate)+onBlur=submitCreate,Enter 提交成功后 setIsCreating(false)卸载 input→onBlur 二次触发,isCreatingPending(异步)+disabled 滞后挡不住→重复 POST(第 2 个同 reqRev→500)。修:submitCreate 加同步 useRef 守卫(提交中早返+置位+onSettled 复位),只挡同次重入、不挡首次/失焦补提交。②WorkspacePage expectedWorkRevision 兜底:原 workRevision(work)??1,work 详情异步未加载时兜成 1、但真实 revision 已 >1→乐观锁冲突。改传真实 revision(未加载 undefined→ChapterPanel 既有 ==null 早返挡过早提交)。

实证:单次新建 POST 修前 2(第 1 成功+第 2 1041000002)→修后 6 轮恒 1;chapter-create-delete 连跑 8 次全绿。相邻写路 spec 不回归、tsc 0 错、editor 单测 33/33。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:47:28 -07:00
lili
80106c2d40 docs(admin-e2e): 回写 admin governance e2e 转真后端全收口(account/market/jobs/meta governance 12 真连 0 skip)
进度总账补 4 entry:account 子域 MVP+基建(c5d1762)、market 下架/申诉真打(ce637ac)、jobs 重试/取消/来源重试(2d06ec5)、governance config 拆 6 子系统真连(6bd9030)。纠正 jobs entry 沿用的"muse_function_chain/muse_protection_node 缺表"误判前提(实为 muse_meta_* 表在缺种子、agent 漏 meta_ 前缀)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:07:31 -07:00
lili
6bd90301a5 test(admin-e2e): governance config 全页巡航转真连——拆 6 子系统真连+灌系统级种子(admin e2e 0 skip 全收口)
承用户选 B(补 admin config 断层)。前提纠正:原 skip 注释"切片库根本没有 muse_function_chain/muse_protection_node 表"误判——psql 实证真表名带 meta_ 前缀=muse_meta_function_chain/muse_meta_protection_node(V3 schema、都在 muse_slice_live、行数 0),真断层是缺系统级公共治理对象种子、非缺表/缺功能。

每锚点真表+真后端过滤契约(curl 实证):story.draft 元结构=muse_meta_schema(列表无 status 过滤);故事链路=muse_meta_function_chain(listQuery 只放行 status=active、displayName 取 chain_snapshot.displayName);事实校验保护节点=muse_meta_protection_node(status=active+policy_snapshot->>chainKey 绑定链路、irreplaceable);候选生成 Prompt=muse_prompt(非 muse_ai_prompt);系统故事智能体=muse_agent(非 muse_ai_agent、agent_type=system、scope=all 不过滤);系统世界观库=muse_knowledge_base(kb_type=global、owner_user_id=0)。

global-setup 加 resetMetaGovernanceFixture(7 幂等 upsert ON CONFLICT、tenant_id=1、照 resetMarketFixture/resetJobsFixture 范式)。spec 删 :456 skip→拆 6 条细粒度真连用例(元结构/功能编排/AI/全局知识/市场/New-API),修 2 处 strict-mode 多命中。New-API 锚点契约纠正(mock 期 user-e2e/usage-e2e 伪造值):真后端绑定行是用户数字 id 字符串、用量 recordId 是聚合派生 {userId}:{period},改对真锚点(活体用户+1:month)、无后端缺口。

独立核实:连跑全量 e2e x2 各 12 passed/0 skipped(account/market/jobs 既有 6 真连无回归、幂等可复现);psql 复核 6 锚点种子真灌(function_chain/protection_node active、muse_prompt/muse_agent system/global KB 各 1 行真实契约)。至此 admin governance e2e 从全 page.route mock 全转真后端:12 真连用例 0 skip。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:05:37 -07:00
lili
2d06ec5f31 test(admin-e2e): jobs 子域转真连(重试/取消/来源重试真打+真 PG 反查)、governance config 断层如实标注 skip
jobs 真连(反假绿:真打写命令+真 PG 反查 muse_ai_job 派生行/状态):①重试(:262)→后端校验 retryable 新插 operation_id=adminRetryJob 同 retry_group queued 子 job(MuseJobServiceImpl.retryAdminJob 纯 DB 状态机、活体 code:0),反查派生子 job 行数;②取消+来源重试(:291)→cancel 改 muse_ai_job.status=cancelled、source retry 新插 job_type=source_event_retry job(muse_ai_source_event 90003 needs_recheck 锚点),反查状态/派生行。关键坑:切片库后台 AI runtime worker ~3s 抢 queued→failed,取消锚点须用 running(worker 不接管、前端 canCancelJob 放行);queued 锚点活体 cancel 真返 1040100014 不可取消。

global-setup 加 resetJobsFixture:幂等 seed 90001(failed/retryable muse_ai_job)/90002(running muse_ai_job)/90003(needs_recheck muse_ai_source_event)+清派生子 job/source_event_retry/命令幂等行,每轮自愈。真契约:retry 请求体只接受 {commandId}(JobRetryReqVO 仅此字段、reason 仅 UI 留痕不外发);cancel/source-retry 接受 {commandId,reason}。旧 skip 靠 mock 拦截 payload 字段,改真打+DB 派生行反查(等价更强),删 museAdminPayloadsByPage 收集器。

核心治理配置页(:456)保留 skip:非端点 500,而是切片数据/表断层——muse_function_chain/muse_protection_node 表在 muse_slice_live 根本不存在(psql to_regclass 均 None)、AI Prompt/全局知识库/story.draft 切片未灌种子,faithfully 转需跨 6 子系统伪造数据且两表连结构都没有,不硬转。用例上方写明断层+待补后端项。

独立核实:连跑全量 account+market+jobs e2e 6 passed/1 skipped(背靠背幂等无第二轮假红);psql 复核 90002=cancelled、retry 派生子 job=1、source_event_retry job=1、:456 断层表均 None(证标注诚实)。待补后端:①切片库缺 muse_function_chain/muse_protection_node 表 ②AI Prompt/全局 KB/story.draft 种子 ③jobs/source 三写命令后端无 P1r 真库 IT(现 Mockito 单测、本次 e2e 真连可视首个端到端真验)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:32:21 -07:00
lili
ce637ac2b6 test(admin-e2e): market 子域转真后端真连(下架/申诉真打+真 PG 反查落库)
market 5 个 skip 用例全是 MSW payload 拦截的负向断言(验前端预览绑定守卫不发陈旧 payload、靠 museAdminPayloadsByPage),真后端 MSW-off 无 payload 收集器无法逐字搬、且纯前端逻辑已 vitest 覆盖,故替换为真后端真连用例。

真连(反假绿:不只看 UI toast,真 PG 反查 muse_market_* 真实行):①市场治理页渲染三工作台(按激活 tabpanel 收口,ant Tabs 不卸载隐藏 pane);②下架真打命令→真 PG 反查 listing_status=delisted+新增 1 条 applied delist 治理动作;③申诉 maintained 真打处理→真 PG 反查 status=maintained、resolver_id=1。global-setup 加 resetMarketFixture(资产复位 listed+申诉复位 supplementing+软删历轮累积终态申诉(42 条 closed 挤出首页锚点)+清理治理动作/预览)、每轮幂等自愈。

揪出 mock 臆想契约:assetId/appealId 是数字串(非 asset-e2e);publish status DB submitted→API pending(后端 toOpenApiStatus 唯一特例、mock 四态不成立);appeal.resolution 列存处理理由文本非结论枚举(结论在 status);delist expectedStatus 只接受 listed(传别的 400);preview actionType 实为 5 值(含 review_rejection)非 4 值。

isIgnoredRuntimeIssue 增忽略 Failed to load resource: net::ERR_*(资源懒加载抖动、非应用错误,命令正确性另有真 PG 反查兜底)——同解 account 首跑偶发红根因(原误判 console.error,实为 dev-server 负载下 chunk 懒加载超时)。独立连跑全量 account+market e2e x2 各 4 passed;psql 复核 asset1=delisted/appeal1=maintained resolver=1/gov_action=1,与报告一致。restore 票据路径 e2e 未覆盖(用例走 maintained、后端不消费 restore 预览),restore 仍只 mock-service 单测无真 PG IT、缺口待补(:397 注释标注)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:06:17 -07:00
lili
c5d1762faa test(admin-e2e): governance e2e 转真后端基建 + account 子域 MVP(反假绿)
admin-governance.spec 此前全 page.route mock /admin-api/muse/**(~20 端点)、前后端契约从未端到端跑;认证注入 localStorage key 硬编码 muse-vben-antd-... 实为 undefined-5.7.0-dev-core-access(VITE_APP_NAMESPACE 未定义→运行时 undefined)、mock 下从不暴露。

命门(实证打通):①认证=与 studio 共用 mock-token Bearer test1(mockSecret test+userId1);②权限=admin 用户原无角色(system_user_role 空)→403,globalSetup 幂等 seed system_user_role(1,1)(super_admin)+DEL redis user_role_ids:1 刷权限缓存→超管跳过 @PreAuthorize;③代理=admin vite 已硬编码 /admin-api→48080、nitroMock 默认关。

基建:新建 global-setup(seed user_role+DEL redis+PG 复位)、playwright.config 加 globalSetup+workers:1、加 pg。spec 改真 localStorage key+token test1+删 routeMuseAdminApis mock(catch-all /admin-api/** 补 tenant-id:1 真打 48080;notify/dict/tenant 平台外壳保留 mock 因切片库无 notify 表返 500)+get-permission-info 走真后端。account 子域真连:真分页 {pageNo,pageSize,total,list} 前端 PageResult 只读 list/total 契约兼容;其他 8 子域 test.skip。独立连跑 15 次绿(含冷启动)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:38:56 -07:00
lili
f44c045315 docs(market): 回写 install isAcquired enrich 假绿修复(进度总账+模块 .agent)
market install 用户可见假绿真因=MarketAssetQueryServiceImpl 读模型裸硬编 isAcquired/isInstalled false(install 后端真实已验)、致安装按钮永不渲染;enrich 与 install 写端口同源修复(commit 37e7a8d)。记教训:读模型 enrich 须与写端口校验同源、改 module 跑 server IT 须先 mvn install。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:31:50 -07:00
lili
37e7a8dc27 fix(market): 修 install 用户可见假绿——isAcquired/isInstalled/canInstall 按真实授权安装态 enrich
三路盘点发现 market install 头号用户可见假绿:install 后端真实已验(P1rMarketLicenseInstallCompletedApprovalIT 批18 绿),但 MarketAssetQueryServiceImpl 把 isAcquired/isInstalled 裸硬编 false(toCard:181-182 列表 + userActions:386-387 详情 + canInstall:383),致 studio MarketBrowse(assetType!=work && isAcquired && !isInstalled)安装按钮在真后端永不渲染,mock 伪造状态位才现身;批17 IT 把 isAcquired=false 断言为正确→假绿固化。

后端 enrich(读模型、未碰 install 写逻辑/授权语义):仿 isFavorite 范式加 isAcquired(active 授权)/isInstalled(installation)/isInstallable(类型集),与 install 写端口 MarketInstallServiceImpl 严格同源(selectActiveByOwnerAndAsset + INSTALLABLE_ASSET_TYPES={agent,knowledge_base}),避免"显示可装但装不了"新假绿;canInstall=listed && isInstallable && acquired && !installed(对齐 studio assetType!=work 门);批量加载(整页 2 次 IN vs 3N)避免放大 isFavorite 既有 N+1;mapper 加 selectActiveByOwnerAndAssetIds/existsByUserAndAsset/selectByUserAndAssetIds;批17 IT 改三态断言+订正裸写注释。

前端 MarketBrowse 补 onError(install/acquire 失败内联可见提示,对齐 AgentCreateForm/SlotBindingPanel,不再静默吞 ApiError);e2e 新增 market-install.spec(MSW-off:purchase 前置→断安装按钮真渲染→install→psql 验,连跑 2 次)+ global-setup #16 market 表复位。

活体真验(muse_slice_live,重启新 jar 10:08):purchase→isAcquired=T/canInstall=T(修前恒 false)→install→isInstalled=T/canInstall=F;独立 psql+GET 复核 asset1/4(owner1)isAcquired/isInstalled=true。批17 IT 5/5 三态绿(首跑遇 .m2 stale jar 假红、mvn install 刷新转真绿)、market 单测 9/9+11/11+7/7、UI e2e 连跑 2 次 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:28:33 -07:00
lili
5c78a2adc4 docs(ai): 回写槽位绑定 authz 孪生收口(C1/V31)——ADR-020 全部 binding 表无漏网
三路盘点发现 muse_agent_slot_binding 是采纳断层(V30)唯一漏网 binding 表(同型 BIGINT+parseLong 丢字符串 envelope),V31 收口并活体真验(binding authz 列存非空 rpe-local、insert+updateById 两路径)。订正上条总账/模块 .agent 的"未误伤 muse_agent_slot_binding"为同型漏修已收口。至此 knowledge V14 + suggestion/attribution V30 + slot V31 全部 binding 表无漏网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 08:34:44 -07:00
lili
854f18c06a fix(ai): 收口 ADR-020 漏网 binding 表——槽位绑定授权快照 BIGINT→VARCHAR(V31)
muse_agent_slot_binding.authorization_snapshot_id 是采纳断层(ADR-020 方案 A,V30/a16c596)唯一漏网的 binding 表:列 BIGINT、DO Long,bind 时 parseLong(precheck.authorizationSnapshotId) 对真 runtime envelope rpe-local-<uuid> 返 null→授权快照静默丢失、绑定溯源链断。knowledge binding 已 V14、ai_suggestion/content_block_source_attribution 已 V30,此表是同型漏网(三路盘点发现,模块记忆从未记此类型错配)。

- V31:authorization_snapshot_id + source_snapshot_id 两列 BIGINT→VARCHAR(128) USING ::text(仿 V30/V14,source 一并收口避免后续写入被静默截断)。
- MuseAgentSlotBindingDO:两字段 Long→String。
- MuseAgentSlotServiceImpl:bind 两处(insert/updateById persistBinding)直透传 precheck.authorizationSnapshotId(String envelope),删 parseLong 包裹;sameAuthorizationSnapshot 的 parseLong 保留(对字符串 envelope 走 fallback 字符串比较,正确)。
- MuseAgentSlotServiceTest:数值串种子改字符串 envelope + 断言落库幸存(反假绿:旧 parseLong 把 0501/501 归一成 501L 无法区分 precheck 与 request)。

活体真验(muse_slice_live):真 envelope rpe-local-6e29...(issuePermissionEnvelope 签发、过 runtime 授权门)经 precheck→bind,binding authz 列存非空 rpe-local 字符串(insert id=51 + updateById id=50 两路径);列类型 character varying(128);flyway V31 success。修前该列恒 null。单测 26 绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 08:31:21 -07:00
lili
3f59ff9079 docs: 订正 market authz type:integer 表述——经核是主键 ID 引用非 ADR-020 业务标识
深入调研发现 market openapi authorizationSnapshotId(integer)是 muse_market_authorization_snapshot/summary 表主键 ID 引用(physical PK int64)、非 ADR-020 管的业务标识(market 业务标识字段 authorizationSnapshot 已 string、合规);符合 ADR-020"物理主键 Long"故不需对齐,盲目改 integer→string 反违"拒字符串主键"。订正 ADR-020 后果段(架构-03 v12)+ 进度总账 2026-06-25 此前"market type:integer 待对齐(同源 ADR-020)"的不准确表述。market 对外暴露主键 ID 是否违后端-04 属独立契约议题、与 ADR-020 不同源、本轮不改。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 02:36:58 -07:00
lili
fc6afe08b5 docs(agent): 回写 AI 采纳断层修复到 ai/content 模块 .agent(ADR-020 方案 A)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 01:36:52 -07:00
lili
fde0866701 docs(ai): 回写 AI 采纳断层修复(ADR-020 方案 A)——授权快照字符串化全链打通、IT 假绿转真绿
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 01:34:25 -07:00
lili
af4ad4d39d fix(test): 补 P1rContentCore/WorkLifecycleCompletedApprovalIT 缺失的 MetaSchemaQueryApi bean(cd85d9d 遗留)
采纳断层 IT 真跑暴露 cd85d9d(D1-2 work→schema 绑定)遗留:ContentAppServiceImpl 新增 @Resource MetaSchemaQueryApi,但这两 IT 的 CompletedApprovalConfiguration @Import ContentAppServiceImpl 却没供该 bean→NoSuchBeanDefinitionException context 加载失败(IT 此前没真跑、靠未执行假绿)。补 @Bean MetaSchemaQueryApi 匿名实现(对齐仓内既有 @Bean 约定,listActiveSchemasByTargetType→List.of/getActiveSchemaById→null);completed approval 不触发 work→schema 路径(body 无 schemaId→resolveWorkSchemaId 短路)故默认值安全。真 PG 跑 Core12/12+WorkLifecycle1/1=13/13 绿。与采纳断层修复解耦,仅补测试配置不改被测代码。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 01:31:46 -07:00
lili
2ede7cb384 test(studio): accept-suggestion 改真生成删 stub,清除 line176② 最后 AI 假绿(采纳断层已修)
采纳断层修复后(commit a16c596 ADR-020,真候选 authz 字符串 envelope 可采纳),accept-suggestion 正路删 /ai/tasks+/stream stub,复用 ai-generation 真链路:WorkspacePage→AIPanel→真 AI task→SSE done→CandidatePanel 采纳替换→真 suggestion-merges code=0+newRevision 自增。反假绿:authz 真 rpe-local 字符串(非种子数值)、sourceAttribution.parentSuggestionId==真生成 id(证非种子)、block revision 实读动态比对(漂移不影响重复跑)。连跑 2 次 2/2 绿(suggestionId 25→26 revision 72→74)+ ai-generation/agent-slot-bind 回归绿。line176② AI 生成 stub 假绿完全清除。flaky:真 SSE 冷启动偶慢(与 ai-generation 同源,CI retries:2)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 01:24:01 -07:00
lili
a16c59662f fix(ai): 修 AI 生成候选采纳断层,授权快照 id 改字符串承载 envelope(ADR-020 方案 A)
真生成候选 authorization_snapshot_id=null 恒不可采纳(1041001001),根因:runtime envelope 是字符串 rpe-local-uuid 但 authz 列 BIGINT 存不下,numericEnvelopeId/requireNumericAuthorizationSnapshot/parseLongQuietly 三处降级门禁致恒拒。方案 A(人类拍板,ADR-020):V30 迁移 muse_ai_suggestion+muse_content_block_source_attribution 的 authorization_snapshot_id BIGINT→VARCHAR(128)(仿 V14);AI 侧直落字符串 envelope(删 numericEnvelopeId);Content 放开两道数值门(删 requireNumericAuthorizationSnapshot/parseAuthorizationSnapshotId/parseLongQuietly);DO authz Long→String 全调用方适配;揭并修 P1rContentMergeGeneratedSuggestionIT 假绿(原注入数值 9001,真 runtime 不产数值,改真字符串 envelope)。活体真验(muse_slice_live,V30 applied):真生成 suggestion authz 现存 rpe-local 字符串→采纳 merge code=0+block revision 69→70(修复前恒 1041001001)→归因新行 authz 字符串,AI 生成→采纳→Canonical 全链打通。编译+test-compile SUCCESS,112 单测绿,未误伤 muse_agent_slot_binding(不在 V30 范围)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 01:03:54 -07:00
lili
180181e4c7 docs(studio): 订正 accept-suggestion stub 根因为真生成候选 authorization_snapshot_id=null(反假绿调研)
正路仍桩 /ai/tasks 的根因经实测订正(非旧注释"AI 本机不可用/缺审字段"):真生成候选已产审三件套+content,唯一缺 authorization_snapshot_id=null→采纳被拒 1041001001"外部 owner 暂不可用"。根因=真 runtime envelope 是字符串 rpe-local-uuid,MuseAiRuntimeProjectionService.numericEnvelopeId Long.parseLong 失败落 null。**揭 P1rContentMergeGeneratedSuggestionIT 假绿**(注入数值 envelope 9001,真 New-API runtime 不产数值→IT 绿≠活体真候选可采纳)。注释 only 无逻辑改,stub 保留(桩生成段、采纳+负路乐观锁全真打后端反假绿),accept-suggestion 2/2 可重复 + agent-slot-bind/ai-generation 回归绿、tsc 0。后续主线:让真生成链产数值授权快照(numericEnvelopeId 解析 rpe-local-* 或列承载字符串 envelope,后端缺口)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 22:08:41 -07:00
lili
abcc08f109 docs(ai): 回写 AIPanel AI 生成 e2e 已补 + connectAIStream 鉴权 bug 修复(line176② AI 生成假绿闭合)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 18:03:19 -07:00
lili
410322cbc0 fix(studio): AIPanel onDone 改用 ref 读流式正文,消除渲染期跨组件 setState
AIPanel onDone 此前在 setStreamContent 更新函数里调父组件 onCandidateGenerated→AIPanel 渲染期触发 WorkspacePage setState(React warn "Cannot update a component while rendering a different component")。改:streamContentRef 在 onChunk 与 streamContent 同步累计,onDone 直接读 ref 调回调,不再渲染期 setState。ai-generation e2e 再跑 React warning grep=0(消失)、仍 passed(26.2s)。顺带修 AgentPage.contract.test 多余 import React(JSX automatic runtime 不需→TS6133;此前写 test 只跑 vitest 漏跑 tsc、commit 4c069d4 带入)。tsc 全量 0、vitest 102/102。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 18:01:56 -07:00
lili
494c9e9b89 test(studio): 补 AIPanel AI 生成真后端 e2e + 修 connectAIStream 漏鉴权头(反假绿暴露真 bug)
补 ai-generation.spec(真后端不 stub,消除 accept-suggestion stub 假绿,进度总账 line176②):真浏览器 WorkspacePage→AIPanel 发送指令→真后端 AI task→SSE→真 New-API LLM→suggestion 落库。**反假绿暴露真 bug**:connectAIStream(src/lib/sse.ts)漏带 Authorization+tenant-id 头→活体 SSE 必 401/400→done 永收不到→候选永不渲染(被 accept-suggestion 的 stub 长期掩盖)。修:补头,与 connectEventStream/client.ts 同源 @/api/auth。SSE 真行为:后端"持久化事件回放+5s 轮询",运行时只落 done 不落 chunk(streamContent 真链路恒空),真 LLM 文本在 suggestion 记录→断言落 suggestion(API+DB 双证)。四断言反假绿:POST 2xx+code0+taskId / suggestion 真 LLM 文本(非空+阈值+主题宽集合不硬编码句子) / CandidatePanel 采纳按钮 / DB muse_ai_suggestion 新行。自验+子代理连跑 4 次绿(suggestionId 12→13→14→15 各不同真 LLM,11-21s 稳定);vitest 102/102(sse.test 16/16);"AI 本机不可用"旧判断已过时(New-API 在线真生成)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 17:59:10 -07:00
lili
e8ca37c9b9 docs(ai): 回写槽位绑定 UI e2e 已补(02D 替换路径端到端真验)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:20:12 -07:00
lili
1fbe7ae73c test(studio): 补 agent 槽位绑定 UI e2e(AgentPage→真后端替换槽位,反假绿)
承 02D 死锁修复(9115d4f)+ AgentPage 作品选择器(4c069d4),补端到端 UI e2e(进度总账 line176② 缺口)。agent-slot-bind.spec:真浏览器 goto /agents→selectOption work1→点 agent1 卡片→点"绑定选中智能体"→真后端 precheck→bind。三重反假绿:DB 起点 revision=1 + bind 响应 code=0/slotRevision=2 + UI"绑定已更新"提示 + DB 终态 revision 1→2 active agent1。global-setup §15 每轮复位 work1 writing.continuation 槽位(agent1 revision1 active)保证可重复(bind 成功 revision+1 漂移、不复位二次跑红)。MSW off 真连 muse_slice_live;自验 + 子代理各跑均 passed 可重复、tsc 零报错。诚实范围:只覆盖"替换已有槽位",首次创建 UI 仍缺槽位骨架(Override Slot Contract=方案 B,人类架构决策域未做)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:19:44 -07:00
lili
2c9fdb513c docs(ai): 回写 AgentPage workId 硬编码解除(02D 前端槽位绑定 UI 打通)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:57:17 -07:00
lili
4c069d482d fix(studio): AgentPage 槽位绑定改用作品选择器,消除 workId 硬编码
承 02D 后端槽位首次创建死锁修复(9115d4f),前端 AgentPage 此前 SlotBindingPanel 用硬编码 WORK_ID_FOR_SLOT_PREVIEW=1(盘点 line176② workId 硬编码),槽位绑定无法用于真实作品。修:接入 useWorkList 作品列表 + 作品选择下拉,SlotBindingPanel 按所选作品 workId 查询/绑定槽位,空作品时提示先建作品。SlotBindingPanel 绑定流(precheck→bind)本就完整(盘点"无真正绑定流"过时:实为后端死锁挡着 bind 必失败,后端修复后真后端 curl 已验 precheck→bind→首次建 binding)。补 AgentPage.contract.test(作品选择→正确 workId 下传 + 非硬编码反向验证)。tsc/eslint 绿,vitest 101→102。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:56:01 -07:00
lili
260f11426d docs(ai): 回写 02D 槽位死锁修复 + AI 生成命脉真后端端到端打通
02D 槽位首次创建死锁修复(9115d4f)+ 前端 MVP agentSlotKey 接线(df063cb)+ P-A 检索修复(86c6dba)逐条破除进度总账 line176"AI 生成四重阻塞"。真后端 happy-path 真验(muse_slice_live):work1 writing.continuation precheck(不再 forbidden)→bind 首次建 binding(slotRevision1 active)→AI task 用 agentSlotKey→agent1→completed+suggestion7(真 LLM"星环大陆魔法体系"续写 finishReason stop)。最大假绿点(AI 生成 e2e 一律 stub /ai/tasks)消除。仍缺 Override Slot Contract 主数据(方案 B)/SlotBindingPanel UI 深链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:37:03 -07:00
lili
9115d4f95f fix(ai): 修 02D 槽位绑定首次创建死锁,precheck/bind 改 upsert + 补 active 唯一约束
根因:precheck(line102)/bind(line182)都 requireSlotBinding(binding!=null)缺行抛 AI_RESOURCE_FORBIDDEN;但"替换"是设计中唯一创建入口(替换=首次写入,无独立创建端点是设计有意,见后端-04 line748/产品-02D line507),要求被替换行先存在→死锁,首次绑定永不可达。work4 seed binding 是 E2E 绕此 bug 手插非设计常态。修:precheck 缺行放行;bind 抽 persistBinding upsert(有行 updateById 沿用乐观锁 revision+1,无行 insert revision=1 避免首次 expectedSlotRevision null 拆箱 NPE);V29 补 active partial unique index(tenant+work+slot WHERE status=active,并发首次写兜底);前端 mock protected 槽位对齐后端 startsWith(protected:)口径。验证:MuseAgentSlotServiceTest 26/26 + AppMuseAgentSlotControllerAnnotationTest 4/4 + 前端 useAgents/AIPanel.contract 4/4;handoff/幂等/乐观锁不破坏。范围:不建 Override Slot Contract 主数据(B)/不碰默认 agent 来源/不动 runtime 授权。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:09:53 -07:00
lili
df063cbacd feat(studio): AI 生成提交补全上下文引用(workId/blockId/agentSlotKey),消除前端假绿
AIPanel 此前只传 commandId/intent/contextScope,残缺上下文被宽松 mock 掩盖(假绿)。补全:Props 接收 + payload 下传 workId(必填)/blockId/chapterId/agentSlotKey,WorkspacePage 透传真实 workId(useParams)+activeBlock.id+activeChapterId,agentSlotKey 续写默认 writing.continuation,接通槽位绑定↔生成断层。防假绿:mock /ai/tasks 收紧 workId 必填(40011);contract test 断言 body 含 workId/blockId/agentSlotKey(反向验证:删 workId 下传则测试变红)。范围:未做 agentOverrideRef UI/AgentPage 硬编码/EditorPage 重构。验证:全量单测 101/101 + tsc -b --noEmit exit 0。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 09:01:52 -07:00
lili
8e6e320cc1 docs(ai): 回写 P-A 检索命中打通到模块 .agent,专题-03 P-A/P-B/P-C 完整 e2e 真验
P-A 根因=document_ids null 入 body 被 RAGFlow 拒(code 102),已修 86c6dba;task7 contextAssembly chunkCount=1 retrievedKbIds=[2] authorizationSnapshotIds=[authsnap-e2e-1] + LLM MiniMax-M2.5 grounding 续写。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 07:22:43 -07:00
lili
86c6dbabc2 fix(knowledge): RAGFlow 检索 document_ids 为 null 时不入 body,修 P-A 上下文检索永不命中
根因:retrieveChunks 把 document_ids 以 null 放入 body,RAGFlow 要求其为 list,返回 code 102 "documents should be a list" → 检索 fail-closed → chunkCount=0。P-A 检索从未命中(task3/4/5/6 全 0)即此 bug,与 embedding/timeout/数据/授权均无关。修:null 时不传 document_ids(按授权 dataset 全量检索,符合 P-A 检索整个 KB 语义)。补 retrieveChunksShouldOmitDocumentIdsFromBodyWhenNull 回归测试(RagFlowClient 23/0、Retrieval 11/0 全绿)。真验:task7 contextAssembly chunkCount=1 retrievedKbIds=[2] authorizationSnapshotIds=[authsnap-e2e-1],LLM MiniMax-M2.5 基于 grounding 续写,P-A/P-B/P-C 完整 e2e 打通。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 07:20:07 -07:00
lili
96f8052c94 docs(ai): 回写 AI runtime 生成 e2e 端到端打通里程碑 + P-A RAGFlow 待办到模块 .agent
方案1(d647f0c)+D(4dadc7b)+agent modelKey+New-API 配置 → task5 MiniMax-M2.5 真 LLM 生成(P-B/P-C ✓);P-A 检索命中仍卡 RAGFlow 数据层(don't own dataset+chunk_count=0,外部依赖)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 06:38:21 -07:00
lili
4dadc7bae3 fix(framework): DefaultDBFieldHandler 无登录用户时 creator/updater 兜底 system,根治 scheduled 写 null 违约
问题: AI runtime 异步链(dispatcher/executor/recorder/projection)在 scheduled 线程 insert/update muse_ai_* 时 creator/updater 写 null 触发 NOT NULL 违约 → recordRequested insert 即回滚抛 → job 卡 running/queued、AI 执行恒失败(runtime_call 0 行)。

根因: BaseDO creator/updater 带 @TableField(jdbcType=VARCHAR),fill 字段即使 null 也被 MyBatis 强制入 SQL 列;DefaultDBFieldHandler 仅当登录用户存在才回填,scheduled worker 无登录上下文 → 写 null → 违约。insert+update 同病。上一版 5d0f17a 误判 insert 靠 default 兜底,只补了 updateById,被 e2e(runtime_call 0 行)证伪。

修正: insertFill/updateFill 无登录用户时 creator/updater 兜底 SYSTEM_OPERATOR("system"),一处根治所有模块 scheduled/async 写;回退 5d0f17a 局部 setUpdater(已被统一覆盖)。OAuth2TokenServiceImplTest 的 assertPojoEquals 补 creator/updater 忽略(token 创建无登录,DB 兜底 system 与内存返回对象不一致;auto-fill 字段本不应参与内存 vs DB 对比,与同测试既有忽略一致)。

验证: 框架+AI 回归 92/0;全量 381 测试类中 D 仅触发 OAuth2 2 断言(已修),余 Pay(Redis NOAUTH)/Knowledge(mock NPE)/P1r(meta 文件)为预存/环境失败、与 D 无关;e2e task3 executor 完整跑通——runtime_call 落库(creator/updater=system)、job/generation/call 全写回终态、无违约、P-C contextAssembly 固化进 source_summary。

注: 剩余 AI_NEW_API_UNAVAILABLE(infra.env 未配 MUSE_AI_NEW_API_*,adapter 走 Unavailable 兜底) + P-A 检索 0 chunks(KB 状态 disabled/draft 非 active) 为环境/数据 gap,非代码。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 04:28:33 -07:00
lili
5d0f17a410 fix(ai): AI 异步 runtime 链补 updater 回填,修 scheduled 写 muse_ai_* updater null 死锁
问题: 剥离 sourceSnapshotId 后 AI task 首次真正进入 executor 执行,撞上预存 bug——AI 异步 runtime 链(dispatcher failClaimedJob、recorder recordFinished、projection createShadow)在 scheduled 线程用 new DO + updateById,yudao DefaultDBFieldHandler.updateFill 仅当登录用户存在才回填 updater(if userId!=null && updater==null);worker 线程无登录上下文 → updater 保持 null → updater 列(fill=UPDATE)进 SET=null → muse_ai_job/call/generation updater NOT NULL 违约 → 写回失败 → job 永久 running、task 卡 queued。

根因对比: knowledge parse worker 用 selectById DO(updater 保留原值)故不中招;AI 异步链用 new DO(updater=null)中招。该链此前从未在真实 scheduled 环境跑过(长期被 runtime permission 死锁遮蔽),方案 1 修复后首次触达才暴露。

修正(局部): 三处 new-DO updateById 显式 setUpdater(ownerUserId 保持 task 链审计连贯,fallback ai-runtime);insert 路径靠列 default '' 兜底不违约,不改。

验证: dispatcher 5 + projection 5 + permission 15 + MuseAiTaskService 40 全绿;待 e2e 重跑 AI task 坐实 job 推进 + 检索 snapshot。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 01:51:57 -07:00
lili
d647f0c8d9 fix(ai): runtime 授权命中剥离 sourceSnapshotId,修 AI 执行恒 fail-closed 死结
问题: ProjectionSecurityRuntimePermissionFacade 的 runtime permission 门要求 grant.scope.sourceSnapshotId 精确匹配(SQL WHERE + Java scope 校验双重),但 sourceSnapshotId 每次 task 随机生成(ContentMuseWorkOwnerFacade:82 = "src-"+UUID)、且 grant 须在 task 提交前置存在 → admin 无法预审批含未来随机值的 grant → P1R-4 下任何 AI 执行(含 agent test)永远 fail-closed 被拒。

根因: 授权链两侧粒度语义错配——校验侧按 per-execution(含随机执行证据)匹配,产出侧仅有 per-registration(admin 预登记)能力;sourceSnapshotId 本是单次执行的事后审计证据,被误当成能力授权命中条件。

修正(最小): 从 grant 命中条件剥离 sourceSnapshotId——删 SQL WHERE 条件 + mapper 参数 + requireMatchingScope 校验;保留为 envelope summary 审计字段 + requireCompleteRequest 非空校验(执行证据仍必填)。授权回归能力粒度(operationId/targetType/targetId·targetKey/agentId/resourceRefs,均为可预登记的稳定标识)。

验证: ProjectionFacade 15(含新增 should_issueWhenScopeOmitsSourceSnapshotId)+ MuseAiTaskService 40 + ToolGrantService 6 + LocalApproval 7 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 00:52:05 -07:00
lili
1cf2ab389a docs(knowledge): 回写 parse worker 里程碑 + AI 授权 fail-closed 边界到模块 .agent
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 23:26:28 -07:00
lili
635045cc30 feat(knowledge): 补 parse 轮询推进 worker,打通摄入 parsing→searchable 终态
处理链 startParseDocuments 触发 RAGFlow 解析后置 parsing/processing 即返回,RAGFlow 解析+embedding+索引为异步;此前无 worker 轮询其完成态(pollDocumentStatuses 仅 IT 手动调用),文档永久卡 parsing 无法 searchable。

新增 MuseKnowledgeParseStatusPollWorker(@Scheduled,默认关闭开关 muse.knowledge.parse-poll-worker.enabled):
- 跨租户捞 parsing 任务(selectParsingForPoll + executeIgnore),逐个切回任务租户轮询 RAGFlow 文档状态
- museStatus=searchable(RAGFlow run=done)→ markRagflowParseCompleted(task completed + version processingStatus=searchable → 文档 isSearchable=true,可进检索)
- failed → markRagflowParseFailed;processing → markRagflowParsePolling 刷新进度并保持 parsing
- RAGFlow 临时不可达/轮询异常一律保持 parsing 等下轮重试,绝不误判失败

ProcessingTaskService 补 markRagflowParseCompleted/markRagflowParsePolling;Mapper 补 selectParsingForPoll。
验证: worker 接线 7 + 回归(DocumentService 17 + Facade 3 + ScanService 9 + P-B RetrievalApiImpl 11) 全绿。端到端启用开关后真验。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 21:14:07 -07:00
lili
ec4a02ded2 feat(knowledge): 文本内容安全扫描,打通知识库摄入 scanning 关卡
实现 KnowledgeContentScanService(同步纯文本字符扫描),替换 KnowledgeFileFacade.materialize 恒 scanBlocked 占位:合法文本→scanStatus=passed→放行入 RAG,恶意字符→隔离,扫描异常→fail-closed。

范围:纯文本(txt/md/entry),内容只作检索文本、不渲染,故不做 HTML 消毒。
- L1 硬阻断:非法 UTF-8 / null 字节 / 危险 C0-C1 控制符 / Bidi 覆盖(Trojan Source) / 体量超限
- L2 规整:Unicode NFC + 去零宽 + 统一换行 → 干净内容入库/入 RAG
- L3 软策略:prompt 注入特征仅写 riskSummary 不阻断(误报高,真正防线是 P-A prompt 边界)
- 服务端权威 + fail-closed(对齐 SSOT 契约);特殊字符判定用十六进制码点,避免源码出现字面不可见字符
- MaterializedFile.scanBlocked 加 reasonCode/message;下游 isRagflowAllowed 总开关已就绪,无需改动

设计 spec:docs/agent-specs/2026-06-23-knowledge-content-scan-execution.md
验证:ScanService 9 + Facade 接线 3 + DocumentService 17(无回归) + P-B RetrievalApiImpl 11(无回归) 全绿。端到端真摄入(scan→RAGFlow→检索)验收待 rebuild 重启后补。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 10:28:19 -07:00
lili
a5b91da7a5 fix(infra): 补 muse_slice_live 缺失的 yudao @KeySequence 命名序列(dev 环境修复工具)
slice 库建表时漏建 yudao 各模块命名序列(@KeySequence 依赖),导致 system_login_log 等表 insert 时 SELECT nextval 报序列不存在(admin login 500)、知识库摄入受阻。

新增 sql/dev/muse-slice-sequences-repair-postgres.sql:
- 序列清单=全仓 @KeySequence 扫描(92 个),与代码一致(已 diff 校验无漏无多)
- DO block:CREATE SEQUENCE IF NOT EXISTS(幂等)+ 按对应表 MAX(id) setval 对齐(避免序列从 1 起与既有数据主键冲突);表不存在或主键非 id 则只建序列、跳过对齐
- 只新增序列对象,不改表结构、不动数据,可重跑

适用命名序列版 slice 库(与 sql/dev/yudao-base-schema 的 IDENTITY 自增版策略不同,后者自洽不需此补丁)。对 muse_slice_live 执行后 public 序列 2→93,配合 muse-file-config-master-seed 打通文件存储链路(FILE_SERVICE_UNAVAILABLE 解除)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 07:57:45 -07:00
lili
d07770c701 feat(ai-knowledge): P-C 质量门控可追溯,固化 Context Assembly Snapshot 到生成记录
专题-03 AI 检索串联第三期(P-C):AI 生成时把检索上下文组装结果固化为 Context Assembly Snapshot,内联进 generation.sourceSummary(jsonb,复用现有快照机制,无新表/无 DDL),作为质量评测可追溯输入(§8;门控评分本身归专题-04)。

- facade ContextAssembly 补 assemblySnapshot:status/chunkCount/retrievedKbIds/authorizationSnapshotIds/omittedSources(§8 可追溯)
- executor:检索组装提到 runtimeCommand 层,快照放进 command.inputSummary,经 command 流到 projection
- projection applyRuntimeResponse:把 contextAssembly merge 进 generation.sourceSummary 持久化(command/inputSummary null 防御)
- 整改 P-A 测试债:MuseAiTaskServiceTest 补 knowledgeRetrievalFacade mock(executor 自 P-A 起注入但未接桩,致 runtimeCommand 路径 14 例 NPE)

验证:facade 7 单测(含 snapshot 断言)+ projection 5 + task 40 防回归 + impl 11 回归 + ArchUnit 3 全绿。端到端真链路(真生成验 generation.sourceSummary 含 contextAssembly)验收待补。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 04:19:27 -07:00
lili
5659eb66c6 feat(ai-knowledge): P-B 授权过滤 fail-closed,检索结果补齐 §5.3 合同字段 + omittedSources
专题-03 AI 检索串联第二期(P-B):在 P-A 最小检索链路上叠加按用途授权 + 来源状态门控(fail-closed),检索结果补齐 §5.3 可追溯合同字段,被过滤来源透出 omittedSources 供审计。

- §4.3 用途门:binding.bindingScope 须含 "search" 上下文检索用途(阅读/导出≠检索),否则拒
- §4.3 来源状态门:projection.status ∈ {revoked,recalled,delisted,blocked,owner_missing,unauthorized} 一律拒;active/stale 纳入(stale 非阻断);active binding 无投影则 fail-closed
- §5.3 授权快照门:缺 authorizationSnapshot 的来源不进 Prompt
- §5.3 chunk 补字段:sourceOwner/sourceObjectVersion/authorizationSnapshot/sourceStatus/allowedPurpose
- omittedSources:被授权门过滤的来源(kbId/reason/sourceStatus)透出;executor metadata 透出 omittedSourceCount
- 全部消费已有 binding + source_binding_projection 数据,无新建授权模型/表

验证:knowledge 11 单测 + ai 6 单测 + ArchUnit(BcBoundary/AiGrantRuntime)全绿。端到端真链路(真 RAGFlow 摄入 + 真 New-API 生成 + 授权门生效)验收待补(攒 P-B 后一次做)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 03:59:36 -07:00
lili
987a20b5b7 feat(ai-knowledge): P-A 最小检索串联,AI 生成接入知识库 RAGFlow 检索填充上下文 L3
专题-03 AI 编排上下文核心链路第一期(P-A):打通 AI 生成链消费 knowledge 知识库 RAGFlow 检索,将授权知识片段填入 provider prompt 的上下文 Layer 3(§4.2 授权资料)。

- knowledge-api:新增 MuseKnowledgeRetrievalApi 对外检索端口(BC 合规,他域只依赖 -api)
- knowledge-server:MuseKnowledgeRetrievalApiImpl 实现 work→active binding→kb→active dataset→RAGFlow retrieveChunks→解析 data.chunks→脱敏;最小授权门(tenant/owner/work 必填 fail-closed)+ 检索失败/无命中一律返回 empty 不抛、不阻断主生成链
- ai-server:KnowledgeRetrievalFacade(@Primary,fail-closed 降级)+ executor executionPrompt 注入 L3 检索上下文(无命中退化为仅 metadata、不臆造)
- chunk 字段解析经 RAGFlow /api/v1/retrieval 官方契约验证(content/kb_id/document_id/similarity)

验证:knowledge 7 单测 + ai 4 单测 + ArchUnit(BcBoundary/AiGrantRuntime)全绿;chunk 解析对齐官方 RAGFlow HTTP API 响应结构。端到端真链路(真 RAGFlow 摄入 + 真 New-API 生成)验收待补。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 02:18:40 -07:00
lili
9ad619fcd6 docs(ai): AI 生成链↔knowledge RAGFlow 检索串联评审版(专题-03 核心)
2 路调研(反假绿 file:line)裁定 AI 检索消费链路:
- 缺口=中间层非基建:两端齐备(executionPrompt 明文"Source text not included this phase";
  knowledge retrieveChunks 已被真实 RAGFlow IT 验收 chunksCount>0、但 0 对外暴露、生产调用方 0),
  缺 knowledge-api 检索端口 + AI 侧 Context Assembly 层
- 外部全在线可真验(RAGFlow status:ok + New-API MiniMax-M2.5 实证)
- 专题-03 §4 四层上下文 + §5.3 检索结果合同 + §4.3 按用途授权过滤为硬约束(fail-closed)
- 建议分 3 期:P-A 最小检索串联真验 → P-B 授权过滤 fail-closed → P-C 质量门控快照

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 01:22:44 -07:00
lili
b5a6b1b423 docs(handoff): market 资产物化架构评审版(裁决伪缺口 + O1 跨租户验证)
2 路调研 + O1 验证(反假绿 file:line)裁决"market 资产物化":
- B(内容副本)与产品-02F:135 禁止项 + Candidate Envelope 已确认决策冲突 → 否
- O1 实证:单租户运行(system_tenant 仅 id=1)+ AI 消费链路(binding→kb 正文)未建成
  (ai application 全量 grep 零命中)→ C/B' 解决的跨租户可读问题当前不触发、
  服务的消费场景不存在 → 双重假想未来建设(违 YAGNI)
- 结论:整条物化主线暂缓,前置(真多租户 or AI 检索消费链路/RAGFlow)就绪前不投入
- SSOT 内部矛盾(A 不物化 vs B 物化)待人类裁决;V27 物化注释系 P2 自写、证据弱

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 00:52:47 -07:00
lili
b9993177eb docs(handoff): 回写 P3 content asset_use 交付(三 owner token 红线全覆盖)
进度总账加 P3 条 + 总览 handoff 行(knowledge P1/agent P2/content P3 三 owner 全覆盖)+
P3 review spec §九实施状态。诚实范围:asset_use=使用授权事实记录非物化、AI 上下文消费另立、
剩 market→kb/agent 资产物化独立主线。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 23:48:40 -07:00