248 Commits

Author SHA1 Message Date
lili
1c2d51bfd4 feat(deploy): S9 单人版 compose 从零部署+黄金旅程活体验收(1a 闭合)
- docker-compose.solo.yml:muse-server 单体+PG+Redis 一体化编排,固化 sql/muse Flyway 迁移只读挂载(mini-infra 从零真验暴露漏挂致 muse 表全缺、AI worker 每秒报 relation does not exist)
- 2.0.0-单人版部署手册.md:双栈拓扑/凭据清单/从零步骤/回滚恢复多用户/Dify 升级约定
- 进度总账:§9 判据 0–7 全留证(黄金旅程 workId98 七步 PG 核验+compose 从零 36 迁移 121 表)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 10:19:47 -07:00
lili
7a6e46b2fe fix(test): S9 整分支收口修 S6d 台账漂移+V35 跳号登记+S8 导入向导 IT 上下文
- 覆盖台账 p1r-api-coverage.json 与生成器去 S6d 已删 RAGFlow 文件引用,知识域 serviceFiles/testFiles 换 Dify 继任,保 32 market dormant 口径不被重生成摧毁
- ContractFirstGateTest 登记 V35 有意跳号(并行线版本预留,V36/V37 已应用 live 库不可回填)+ stale 守卫
- P1rContentImportWizardCompletedApprovalIT 补 MuseAiProperties @Bean(S8 加 @Resource 依赖后极简上下文缺 bean 致 ApplicationContext 加载失败)
- 独立复跑:local 门 65/0F/0E BUILD SUCCESS;import wizard 真PG IT 2/0F/0E(1 live skip)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 10:19:11 -07:00
lili
302603d9d9 refactor(knowledge): S6d 删 RAGFlow 运行时,Dify 转默认装配
S6 Dify grounding 已 live 证成(新 KB→Dify dataset 索引→生成 contextAssembly
chunkCount=1→输出复现 KB-only 专名),RAGFlow 运行时退役。删 HttpRagFlow/
UnavailableRagFlow 两 client + RagFlowKnowledgeRuntimeClientConfiguration 装配
+ 其配置测试 + KnowledgeRuntimeClientTest(整体为 RAGFlow 契约测试)+ RAGFlow
live IT(knowledge 侧 P1rRagFlowLiveAcceptanceIT + muse-server 侧 P1rKnowledge
RuntimeEndToEndLiveAcceptanceIT,§9.3 明示退役;Dify e2e 已活体证成、按 content-
filter 记忆不新造 P1r IT 顶替)。

装配转默认:DifyKnowledgeRuntimeClientConfiguration 主 bean 加 matchIfMissing=true
(provider 未设→Dify);新增 @ConditionalOnMissingBean 兜底 unavailableKnowledge
RuntimeClient(原无通用兜底,provider=ragflow 显式值下主 bean havingValue=dify 不
匹配会致无 bean 启动失败,兜底补齐后落 Unavailable)。RagFlowKnowledgeRedactor 被
Dify 复用保留;ragflow 属性块/muse_knowledge_ragflow_binding 表(遗留命名存 Dify
ID)不动。market-assembled 双排除的 P1rMarketKbForkMaterializationIT 保留(market+
RAGFlow 双休眠,归 market 恢复路径,符合 S3「排除不删」)。

验证:knowledge-server 单测 300/0/0/0 BUILD SUCCESS;knowledge+muse-server 全分支
test-compile BUILD SUCCESS(MVN_EXIT=0);DifyKnowledgeRuntimeClientConfigurationTest
8 全绿验三态(缺省→Dify/ragflow→Unavailable/缺省未配→fail-closed Unavailable)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 09:06:32 -07:00
lili
9057dc8df0 fix(ai): 补修 S8 接口加 providerKey 破坏 muse-server 导入向导 IT 编译
S8(0b109a29)给 MuseAiImportLlmParser 接口加 providerKey() 后它不再是函数式
接口,而 P1rContentImportWizardCompletedApprovalIT 的 importLlmParser() 测试 bean
仍以 lambda 提供 stub → muse-server test-compile 断裂。当时 S8 只跑 ai 模块单测
(20/0/0/0)、未编 muse-server 整分支,故漏(整分支视角收口价值)。改 lambda 为匿名
类实现 parse+providerKey;该 IT 只装配单个 parser bean、resolveImportLlmParser 对
size==1 直接返回,providerKey 不参与选择,返回 "stub" 占位。

验证:mvn -pl muse-server -am test-compile BUILD SUCCESS(MVN_EXIT=0)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 09:06:31 -07:00
lili
0b109a2961 feat(ai): S8 导入解析切 Dify chat 解析器 + provider 选择
MuseAiImportParseService 从单点注入 NewApiMuseAiImportLlmParser 改为按
muse.ai.import.provider(缺省 dify)从 List<MuseAiImportLlmParser> 选择;来源标识
由选中 parser 的 summary.parser 自报(dify_import_llm / new_api_import_llm)。

新增 DifyMuseAiImportLlmParser:走 Dify「muse-全书解析」chat app(passthrough M3、
克隆自写作 app)的 /chat-messages blocking 调用,把镜像 New-API 的 system+user 解析
prompt 合并成一条 query 发出,从 answer 消费章节 JSON。语义逐条对齐 New-API 版:
401/403 fail-closed 不重试、408/429/5xx 退避重试、输入上限 180k、空/超 300 章节、
脱敏 summary、直连绕代理、key 不落库不打印。截断检测差异:Dify chat 无 finish_reason,
改为对 answer 做 JSON 完整性校验(解析失败→AI_IMPORT_LLM_TRUNCATED 不可重试)。
MuseAiProperties.Dify 补 maxAttempts/retryBackoffSeconds;新增 ImportParse.provider。

规格允许 app/workflow;创始人定 chat app 顶替空 workflow 壳 fed4d25c。p1r 配置
MUSE_AI_DIFY_PARSER_APP_ID/API_KEY 指向新 chat app 17438ceb。

验证(独立重跑核验,不采信子代理自报):
- ai 模块单测 20/0/0/0(DifyImportLlmParser 7、ImportParseService provider 选择 11、
  NewApi 2)+ content ImportParseService IT 16/0/0/0,MVN_EXIT=0 BUILD SUCCESS
- Dify 解析 app 直连 /v1/chat-messages 冒烟真出严格章节 JSON {"chapters":[...]}
- 代码 review:确认真 chat 契约(/chat-messages、读 answer、无 workflow 残留)
未做:完整上传链 live 全书解析(import→对象存储→storageRef→parse job→LLM)属 S9
黄金旅程/import-wizard.spec.ts 范畴——inline contentText 走同步 splitter 绕 LLM,
LLM 路径需对象存储上传流,非本次 parser 改动引入。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 07:59:26 -07:00
lili
bdc07a4321 fix(ai): muse-server 补 muse.ai.dify.credentials 修 Dify 生成凭据无法绑定
单体 muse-server 只加载自身 application.yaml,muse-module-ai-server 的同名
application.yaml(含 muse.ai.dify)被 classpath 遮蔽不生效。enabled/base-url
等标量能靠 MUSE_AI_DIFY_* 环境变量 relaxed-binding,但 credentials 是 List、
无法用扁平环境变量绑定 → 运行时列表为空 → RealDifyMuseAiRuntimeClient.apiKey()
恒返 null → 任何 Dify 生成秒失败于 AI_AGENT_DIFY_CREDENTIAL_REQUIRED。此前 S7d
只有 mock properties 的单测、从未经 muse-server 端到端活体验证,故未暴露。

修法:在 muse-server 自身 application.yaml 的 muse.ai 下补 dify.credentials
列表块(api-key 仍从环境变量注入,禁止明文落库)。

活体验证(muse_slice_live,官方 start-muse-server-infra.sh 重建+仅 p1r 标量 env、
无索引 env 兜底):POST /app-api/muse/ai/tasks(work1 writing.continuation)
→ agent v8(runtimeProvider=dify)→ RealDify → Dify /v1/chat-messages(写作 app
75f105e8, MiniMax-M3)→ generation taskId=117 status=completed 无 error →
suggestion id=107 落库真 M3 续写正文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 04:50:27 -07:00
lili
13bd910c8f feat(knowledge): S6 摄入轮询键 documentId→batch(Dify 按 batch 轮询 indexing-status)
为 muse_knowledge_processing_task 加 runtime_batch_id 列并落库 Dify 上传返回的索引批次(从 uploadResult.summary 的 batch 键抽取)。poll worker 取 runtimeBatchId 非空优先、否则回退 ragflowDocumentId 作轮询键,RAGFlow 无 batch 路径逐字不变;skip gate 放宽为 documentId 与 batch 都空才跳过。

DDL 采用新迁移 V37 ALTER TABLE ADD COLUMN,非回编 V14 建表语句——沿用 sql/muse append-only 约定(V24/V27/V30/V31 同法),避免破坏已应用库(dev/live)的 Flyway 校验和。

验证:mvn -pl muse-module-knowledge-server -am test 目标两类全绿(PollWorkerTest 9/0/0/0、DocumentServiceTest 17/0/0/0,聚合 Tests run 26 Failures 0 Errors 0 Skipped 0,BUILD SUCCESS)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 03:45:46 -07:00
lili
a8f5e912f5 feat(knowledge): S6c 检索多 dataset 逐库扇出+按相似度合并(Dify 单库端点适配)
Dify 的 retrieve 是单 dataset 端点、一次只检索一个库;把 MuseKnowledgeRetrievalApiImpl 从一次
多库调用(RAGFlow 原生多 dataset_ids)改为逐授权库检索:每次 chunk 直接归属本次检索的授权来源
(Dify 单库响应无 dataset_id、无法事后反查),再按相似度降序合并、截断到全局 topK。单库失败降级
跳过并记可追溯日志、全部失败回传代表性失败类。顺序执行(非并行)保留租户 ThreadLocal 上下文,
避免并行池线程丢上下文的隔离风险;内测期单作品 KB 数少延迟可接受,并行留作后续优化。授权双门
/§5.3 合同字段/同库多来源去重语义不变。

测试 18/0/0/0:15 个原测试(含 SPIKE 越权 + uRetrieve)证明单来源行为逐字不变,新增多库合并排序
/单库失败降级/全库失败三例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 03:12:55 -07:00
lili
09ff354e2f feat(knowledge): S6b DifyKnowledgeRuntimeClient adapter(5 操作)+ provider 互斥装配
S6 第二子步(不改检索/上传/轮询流程、不加 DDL、不删 RAGFlow):新增 DifyKnowledgeRuntimeClient
实现 KnowledgeRuntimeClient 5 操作,HTTP 范式对齐现有 Dify/RagFlow client(JDK HttpClient+直连
ProxySelector+Bearer(dataset-api-key)+RagFlowKnowledgeRedactor 脱敏+可测 send() 缝+fail-closed)。
API 映射以 S1 P1rDifyDatasetsContractLiveIT 为准:createDataset POST /v1/datasets(顶层 id)、
uploadDocuments create-by-file(嵌套 document.id + 顶层 batch)、startParse 降级 no-op(Dify 上传即
索引)、pollDocumentStatuses indexing-status(batch 主键、data 数组/对象两态归一)、retrieveChunks
retrieve(单库,records[].segment.content/score 归一成下游已消费的 data.chunks[].content/similarity)。

装配互斥:新增共享选择器 muse.knowledge.runtime-provider——Dify 仅 =dify 装配,RAGFlow =ragflow
或缺省(matchIfMissing=true)装配,确保单人只装一个 bean(取代非确定的 @ConditionalOnMissingBean
扫描顺序)。**默认保持 RAGFlow、既有部署零变更;激活 Dify 需 S9 solo 配置设 runtime-provider=dify**。
新增 UnavailableKnowledgeRuntimeClient 通用 fail-closed 桩。未摘 RAGFlow(S6d)。

过渡缺口(属 S6c):adapter 单库检索只取首个 datasetId,多 KB fan-out+合并归 S6c 的 RetrievalApiImpl;
poll batch 依赖 S6c 把 worker 轮询主键改喂 batch;归一成 data.chunks[] 形态使 S6c 只需加 fan-out。

验证:knowledge 模块 315 用例全绿(DifyClientTest 22 + ConfigTest 8 + 旧 RAGFlow 未回归),BUILD
SUCCESS;装配 ApplicationContextRunner 6 组场景实证任何组合只装 1 bean。真连冒烟归 S6e。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 01:58:34 -07:00
lili
b583bd6dc6 feat(ai): S7d 生成 provider 切 Dify 的 fail-closed 硬化 + 超时对齐(代码层)
分支①第四步代码/配置层:RoutingMuseAiRuntimeClient 补 Dify 装配为占位 Unavailable 时的 fail-closed
——dify 选中但未装配/凭据缺 → 返回 Dify 专属 AI_DIFY_UNAVAILABLE 并拒绝,绝不回退 New-API(此前会
误报 AI_NEW_API_UNAVAILABLE);dify 分支三出口(requiresSourceRefs→REF_INVALID / !difyAvailable→
UNAVAILABLE / 否则 difyClient.execute)均不触碰 newApiClient(亲验)。Dify non-stream-read 超时默认
90→180s 对齐总预算(180≤180<SSE 死线 240);单人 solo-compose.env.example 启用 Dify 块(凭据取自
既有 S1 DIFY 块,未新造);New-API adapter 与配置保留(S8 才摘)。

在用 Agent 的 runtimeProvider 存于 muse_ai_agent_version.config(运行时 DB JSON 列)非静态种子,故真正
把在用 Agent 切 Dify 属 live 数据操作,归 M3 由主会话执行(本提交不含 DB 改动、不切换 live provider,
超时改动在 Dify 未启用前休眠)。

验证:ai 模块 530 用例全绿(新增 fail-closed 不回退 + Dify 完整正文形态 2 例);P1rDifyChatLiveAcceptanceIT
真连 100.64.0.8:18080 验证 wiring/契约/失败映射通过。**M3 live happy-path 阻断**:Dify「muse-写作透传」
app(75f105e8)/chat-messages 返 500(/info 200)= 该 app 模型后端未配好(Dify 侧配置,非 Muse 代码),
代码正确映射 AI_DIFY_PROVIDER_5XX 可重试+fail-closed;待所有者在 Dify 侧修复 app 模型配置后跑 M3。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 01:25:56 -07:00
lili
2ac42a0628 refactor(knowledge): S6a 端口重命名 RagFlow→Knowledge + 裁剪无生产调用操作
S6 第一子步(机械、provider 无关):接口 RagFlowKnowledgeRuntimeClient→KnowledgeRuntimeClient
全量重命名(207 引用,裸旧名 PCRE 精确核验 0 残留);裁掉 7 个已核验无生产调用操作
(updateDatasetConfig/listDatasets/listChunks/runGraphRag/traceGraphRag/getKnowledgeGraph/health,
Command/枚举/实现体/单测清零),接口保留 5 操作(建库/上传/触发解析/轮询/检索);审计
recordRagflowCall→recordRuntimeCall、RagflowCallRecordReq→RuntimeCallRecordReq(旧 token 0/新 13)。
REST 端 MuseKnowledgeGraphQueryService.getKnowledgeGraph(从 Muse 自有 PG 读图,同名不同方法)保留未动。
命名债白名单保留原名:表 muse_knowledge_ragflow_call/_binding、两 DO/Mapper、ragflowDatasetId/
DocumentId 列、KNOWLEDGE_RAGFLOW_* 错误码、FailureClass.RAGFLOW_*(S6 删类步再清)。

两个 opt-in live IT(P1rRagFlowLiveAcceptanceIT、server 的 P1rKnowledgeRuntimeEndToEnd...)原本真调了
被裁操作(health/listChunks/runGraphRag/traceGraphRag),做最小手术删被裁调用/断言、保留 5 操作
happy-path 覆盖(这俩 IT 本就在 S6 后续删/重做)。HttpRagFlowKnowledgeRuntimeClient 等实现类名 S6 删类步保留。

验证:knowledge 模块 285 用例全绿(BUILD SUCCESS);muse-server test-compile 默认 + market-assembled
双 profile 均 BUILD SUCCESS(被改 IT 新鲜编译)。此前 worktree 隔离基线陈旧 320 commit 作废、主树重做。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 01:03:52 -07:00
lili
fcd0623a18 feat(ai): S7b 瞬态全文载体 + SSE chunk 送达 + 决定即清
分支①第二步:新增独立瞬态加密表 muse_ai_generated_fulltext(V36:fulltext_content 经
EncryptTypeHandler AES 加密、expires_at TTL 30min、content_hash/length 供脱敏、决定即删),
仿 MuseAiRuntimePayloadStore 范式建 Store(write/read/purge/cleanupExpired)。执行器拿到成功
RuntimeResult 后把 fullOutput 写瞬态 Store(不在终态 finally purge——出向正文须存活到用户决定);
投影在 done 之前发一条非终态 chunk 引用行(payload 只含 {contentRef:taskId,sequenceNo},绝不带
正文,不落 outbox、不受终态唯一索引);SSE chunkData 遇 contentRef 回瞬态 Store 取正文填 content,
缺失(purge/过期)→空串,兼容旧内联行。采纳(merge facade)/放弃(reject 两路)即 purge。

主权红线(四重亲验):完整正文只存于执行线程内存/瞬态加密表/SSE 传输/客户端,永不进 chunk payload
(只放 ref)、永不进 muse_ai_suggestion/muse_content_block 任何长期列;content_snapshot.content 仍
写脱敏摘要(S7a 口径未动);DO toString 排除正文、Store 日志只算 sha256/length。

验证:ai 模块 528 用例全绿(新增 Store 6 + 投影/流/建议/合并各扩展),BUILD SUCCESS(-am 防 stale)。
真 PG 一次真生成端到端(chunk 携全文/决定后 purge/重连回取)并入 M1 harness,本步未造新 live IT(避
内容过滤器)。DDL:V35 由 S6 占,本表 V36,当前 V34→V36 临时空号,S6 落 V35 填平(Flyway 允许)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 00:29:29 -07:00
lili
916d6c877f feat(ai): S7a 捕获 provider 完整正文 + 护栏/审上移到完整正文
分支①第一步(provider 无关):RuntimeResult 加仅内存 fullOutput 字段承载 provider 完整正文
(供 S7b 瞬态通路),两个 real client(New-API/Dify chat+workflow)在派生 60/80 字摘要前捕获
完整正文并跑护栏,通过才透出。护栏 guardFullOutput 纯静态 provider 无关:空/超长/凭据痕迹/
疑似截断(≥60 字未以句末标点结束)→失败可重试,不信 provider finishReason(Dify 硬编码常量、
New-API 只记录)。「审」输入从脱敏摘要上移到 result.fullOutput(缺省回退摘要,兼容 shadow/历史)。

主权红线(三层亲验):content_snapshot.content 仍写摘要(resolveContentText,不变);完整正文仅
作 review() 局部变量,findings 落库只含布尔/marker 名/长度、审 ID 指纹用 hashCode+length 不可逆,
无正文明文入库;fullOutput 无任何 set/put/序列化/持久化出口,toString 只打 length。

验证:ai 模块 79 用例全绿(MuseAiCandidateReviewServiceTest 11 / MuseAiRuntimeClientTest 22 /
MuseAiRuntimeProjectionServiceTest 6 / MuseAiTaskServiceTest 40),BUILD SUCCESS。改动严格 7 文件。
真实生成经护栏的活体验证并入 M1(S7b real-PG)。附:DDL 协调 S7b 瞬态表改 V36(S6 batch 占 V35)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:59:27 -07:00
lili
92b90878ec fix(solo): 补齐单人版登录栈种子与 OAuth2 scopes 兜底
单人版真实登录(admin 后台 / member studio)所需的基座种子与兜底:
- OAuth2TokenServiceImpl.createAccessToken 增加 normalizeScopes:登录链路不显式传 scope,
  但 PG token 表 scopes 非空约束 → 无兜底会写入失败;统一兜底到客户端默认授权范围。
- yudao-base-seed 补 admin(admin123, status=0)+ super_admin 角色绑定 + default OAuth2 client
  + member 测试账号 15601691388(admin123);ON CONFLICT DO UPDATE 幂等。
- yudao-base-schema / create_tables 给 system_login_log 补 tenant_id(登录写访问日志需要)。
- muse-slice-sequences-repair 补 system_oauth2_* 与 demo 序列;OAuth2 access/refresh token
  复用同一 @KeySequence,按两表 GREATEST 对齐,避免 nextval 撞已存在 id。

验证:OAuth2TokenServiceImplTest 14 tests/0 fail(含新增 testCreateAccessToken_nullScopesUseClientScopes);
种子已灌入 muse_slice_live(admin/member/oauth2 client/user_role/tenant 全就位、口令哈希 = admin123)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:41:29 -07:00
lili
9af471289a fix(solo): 修复 2.0.0 单人版 live 后端启动(DB 口径对齐 + moderation 关停)
标准启动默认落陈旧的 muse_local(仅 V0 baseline、缺 yudao 基座、update_updated_at_column()
函数属第三个角色 muse)→ Flyway V1 CREATE OR REPLACE FUNCTION 报 "must be owner"。唯一健康
的 live 库是 root@muse_slice_live(已迁 V34、含基座+登录种子)。将 application-infra.yaml 与
start-muse-server-infra.sh 的默认库/用户改为 muse_slice_live/root(真实值仍由 infra.env 覆盖)。

S4 关停 spring.ai.model.* 时漏了 moderation;OpenAiModerationAutoConfiguration 默认
matchIfMissing=true → 全量 boot 实例化 openAiModerationModel、无 OpenAI key 直接抛
"OpenAI API key must be set" 使单体启动失败。在 monolith 真正加载的 muse-server/application.yaml
与 ai-server/application.yaml 两处补 moderation: none(单人形态输出合规走自研 MuseAiCandidateReviewService)。

workspace.spec 冒烟原缺 token 注入,被 S5 新增的 AuthGuard 拦重定向 /login → 补 test1 token 注入。
external-deps 记录 Dify 实例被游戏/Muse 共用、workspace 须隔离的约束。

验证:muse-server 干净启动(Started in 22.4s、Flyway up-to-date 零 owner error);MSW-off 创作主线
e2e 33 passed/0 failed/31 隔离(候选采纳/导入/导出/知识草稿/图谱/绑定/agent 生命周期/AI 真生成全绿);
run-p1r-verification.sh local 65 tests/0 fail BUILD SUCCESS。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:41:12 -07:00
zizi
6dcabf69fb feat(solo): 收口治理入口并裁剪 studio 表面
完成 2.0.0 S4 的外部 AI、admin、account 与 solo SQL 收口,并推进 S5 studio 市场/handoff/旧编辑器入口裁剪。S5 的前端单测、构建与 route-only e2e 已留证;MSW-off 创作主线 e2e 仍因本地后端活体启动口径待修正,已在总账标为未完成验收。
2026-07-08 11:45:26 +08:00
zizi
c8a88e71b3 feat(muse): detach market assembly for solo mode 2026-07-08 10:16:41 +08:00
zizi
b9663f52d1 test(p1r): prepare S2 market detach gates 2026-07-07 19:02:23 +08:00
zizi
6f2629302f feat(p1r): add Dify S1 live acceptance 2026-07-07 17:10:40 +08:00
zizi
13b305d4da fix(p1r): align 2.0.0 S0 local gate counts 2026-07-07 14:28:34 +08:00
lili
c2777cc71c feat(ai): 接入Dify运行时Adapter
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 00:57:46 -07:00
lili
0f1ff6e4f2 fix(infra): 修复外部服务代理与RAGFlow检索字段
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 10:28:36 -07:00
lili
0acb249a17 docs(mvp): 校准RC后补状态
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 08:29:08 -07:00
lili
5acb2503b5 feat(studio): 补齐深面入口
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 08:26:47 -07:00
lili
19ff616463 feat(ai): 补齐质量评估执行器
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 08:26:03 -07:00
lili
a5619a3566 feat(content): 补齐导入导出真链路
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 07:40:10 -07:00
lili
facaca1643 feat(admin): 补齐AI系统配置写链路
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 12:52:37 -07:00
lili
8ae812ce6c feat(content): 补本文导入初始化正文
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:54:47 -07:00
lili
3585219637 feat(mvp): 收束1.0.0线A交付闭环
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 10:52:10 -07:00
lili
8b3258e22f test(market): U-verify D0-fork 端到端真验收(真 PG+真 RAGFlow、第四单元)
D0-fork 最后单元:真 PG17+真 RAGFlow 端到端验收、2 IT 真绿(独立复跑确认 57s)。P1rMarketKbForkMaterializationIT(muse-server、跨 knowledge+market 两 BC 须同 Spring 上下文):①fork→安装→物化 installed_ref→检索命中(no_dataset 消除、副本与活 dataset 物理分离);②发布者私有不泄露真证(发布者上架后往活 dataset 真传私有 magic、安装者检索副本拿 magic 当 query 仍只返公开 chunk 不含 magic→d0ForkIsolationProven、U0 spike 反向基线);③幂等+多安装者共享1副本;④AFTER_COMMIT 时序(committedAssetForked/rolledBackAssetForked false:提交才 fork 回滚不 fork);⑤_test 库铁律(muse_p1r_fork_mat_test 绝未指 muse_slice_live)。

market-install-kb-retrieval.spec.ts(studio e2e):检索命中+私有不泄露无独立 UI 入口由 IT 证;安装物化 e2e 标 test.fixme 待 global-setup 补 fork 就绪资产(不伪绿、骨架就位 tsc 过)。召回回滚(D9)如实标开放项:recallAsset 仍 writeSourceStatusBlocked、knowledge 无召回消费者→不自动停用 installed_ref;需新增 market→knowledge 召回传播才闭环(不伪造、不引用不存在的 muse_source_propagation_target)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:58:56 -07:00
lili
d4309ab0e9 test(market): U-retrieve 检索打通(D0-fork 第三单元、RetrievalApiImpl 零改动)
D0-fork 第三单元:验证 installed_ref 物化后检索链自然打通、消除 no_dataset。RetrievalApiImpl 生产代码 0 改动(临时-04 判断属实):U-materialize 已在数据层闭合去污染链(binding.kb_id=本地 kbId、ragflow_binding 指公开副本)→第四门 selectActiveDatasetByKbId 返非空→no_dataset 分支不进→进 RAGFlow 检索;授权快照 knowledge/api 全程 String 透传无 parseLong(ADR-020、无 NumberFormatException);document_ids/metadata_filter 保持 null(命中纯公开副本、无需运行时隔离)。

加 2 单测(MuseKnowledgeRetrievalApiImplTest 15/15):no_dataset 消除+命中(对照基线无 dataset binding 时 no_dataset)、字符串授权快照透传。发布者私有不泄露(真 RAGFlow)+真 PG 端到端留 U-verify。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:33:43 -07:00
lili
30a693e1b7 feat(market): U-materialize 安装侧物化(D0-fork 第二单元、kb_id 去污染)
D0-fork 第二单元:knowledge 绑定路径把"只写引用绑定"升级为建本地 installed_ref KB 实体+binding 指向公开副本 dataset。新增 MarketAssetSourceApi 跨 BC 读端口(market-api+server、读出 发布者kbId/publicForkDatasetId/forkStatus、从 market_asset 自有 source_id+tags JSONB、与 ForkApi 写职责分离);knowledge 经 -api 不读 market .dal。

MuseKnowledgeBindingService:precheck 跨 BC 读市场资产+公开副本(存在/knowledge_base 类型/forkStatus=ready 校验、固化进 precheck 快照)、bind 建 installed_ref KB(kb_type/source_market_asset_id/license_snapshot_id 数值主键 D8/owner/active)+指副本 ragflow_binding 同 @Transactional 原子。kb_id 去污染:market_kb 不再 parseLong(sourceId)当 kbId(那是 assetId)、改本地新建 installed_ref kbId、binding/projection/installed 列表读回全跟随(消除检索 no_dataset 根因)。D6 fail-closed:仅 forkStatus=ready 放行、pending/partial/failed 拒、0 写。幂等(安装者,资产)维度复用。多安装者共享同一 publicForkDatasetId、kb_id 各异不撞 uk。

单测 26 绿(BindingService 16+InstalledService 8+RoundTrip 2)、BcBoundaryArchTest 2/2、编译 BUILD SUCCESS。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:26:57 -07:00
lili
5a938319a8 feat(market): U-fork 发布侧 fork 公开副本(D0-fork 第一单元、进程内事件接线)
D0-fork 第一单元:知识库上架时发布侧 fork 一份只含公开快照文档的专用 dataset、安装者只读共享、物理隔离发布者私有。KnowledgeMarketForkService(核心):公开集界定(上架时刻 searchable/generative active 文档、私有不进副本)+RAGFlow 三步复制(createDataset+逐文档 uploadDocuments+startParseDocuments、无 copy API)+异步重活(幂等键(assetId,version)/部分成功补差集/失败按 FailureClass 重试/审计)。

订阅 glue(人类拍板进程内 Spring 事件、非统一 Events 因其无后端消费机制):事件对象 MarketKbListedEvent 落 market-api(守 BC、market 发 knowledge 听);market markListed publishEvent;knowledge @TransactionalEventListener(AFTER_COMMIT 不绑架审核事务)+@Async(不阻塞审核线程)+TenantUtils(异步租户上下文)+错误隔离。@Scheduled 兜底扫 forkStatus≠ready 重试(进程内事件不持久化、保最终一致、config-gated 默认关)。副本 datasetId+forkStatus 写回 ragflow_binding(market_public_fork+binding_summary JSONB)+market_asset.tags(经 MarketAssetForkApi 供 U-materialize 读)、不加 DDL。移除冗余 outbox kb_listed 双重死代码。

单测 14/14(ForkService 6+Consumer 3+Backfill 5)、BcBoundaryArchTest 2/2(market 不依赖 knowledge)、market-server 212+knowledge-server 268 回归绿、编译 SUCCESS。诚实:端到端为单测层验证、AFTER_COMMIT 真事务时序集成验证留 U-verify。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:05:13 -07:00
lili
a8a26983fc test(market): U0 spike 钉 KB 物化共享越权基线 + 拍 D1=S 回填
market install KB 物化 U0 spike 产 D1 决策证据(只 spike 测试零业务代码):MuseKnowledgeRetrievalApiImplTest +2 case(13/0 独立复跑确认)——①他租户私有 chunk 原样返回证伪租户过滤 ②ArgumentCaptor 抓 RetrieveChunksCommand documentIds/metadataFilter 均 null 证整库扫描零隔离;同作 U4 隔离回归反向基线(隔离补到位后应转红)。活体真 RAGFlow 整库返回坐实。

U0 揪出潜伏 bug:检索发 metadata_filter 但 RAGFlow 官方契约(context7)是 metadata_condition→被静默忽略(乱值条件仍返 baseline)、字段名修正纳入 U3。用户拍 D1=S(补隔离后共享、真最小留痕):临时-03 回填 S 分支定调(隔离优先 metadata_condition+物化打安装维度元数据+U4 复用 spike 反向基线)。进度总账回写方向全链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 09:14:14 -07:00
lili
94545ff87b test(it): 全量 50 P1r 真 PG IT 收尾全绿——修 Planning schema 版本 + live-acceptance 第二代理坑
继抽样 6/6 后跑全量 50 P1r 真 PG IT(用户选继续、IT 层 CI 健康收尾):50/50 全绿(199 用例 0F/0E/1S、1 skip=RagFlow GraphRAG assumeTrue)、含 4 个 LiveAcceptance 真打 New-API/RAGFlow。修 2 预存历史红(均非本 session):

Planning IT 4F:TARGET_VERSION 停 V21 但 savePlanningItem→captureFieldSnapshot 依赖 V25 新增 muse_content_planning_field_snapshot 表(94a2379)→relation does not exist 500;修=21→31(同 Core V30/AiRuntime V31 同向、核心 planning fact/command/outbox 断言不放宽)。4 live-acceptance 502/UNAVAILABLE:第二代理坑——SOCKS 清理只清 socksProxyHost、macOS 系统代理 127.0.0.1:7897 仍被 JVM 注 http.proxyHost、java.net.http.HttpClient 走死代理;反误判=curl --noproxy 直打全 200 证外部健康;修=argLine 加 -Dhttp.proxyHost= -Dhttps.proxyHost= -Djava.net.useSystemProxies=false。external-deps 蒸馏。

anti-false-green:核实 Planning diff 仅 schema 版本非放宽、muse_slice_live 167 表+数据完整未被 IT flyway.clean 误删(_test 库隔离遵守 muse_p1r_*_test)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 02:09:45 -07:00
lili
a0569c6481 test(it): 修 P1rAiRuntimeEndToEndLiveAcceptanceIT 落后产品演进的测试上下文(schema V31+补 bean)
抽样关键链路 P1r 真 PG IT 验证(用户选抽样、6/6 全绿)中发现并修的预存历史红(非本 session、测试基建跟上产品演进):TARGET_VERSION 13→31(ADR-020 V30 把 muse_ai_suggestion.authorization_snapshot_id BIGINT→VARCHAR 承载字符串 envelope,停 V13 会 bigint 类型不匹配)+ 补 MuseAiEventPublishOutboxService 空实现/KnowledgeRetrievalFacade empty context 两 bean(投影/executor 经 ADR-020 outbox+P-A 检索演进新增 @Resource 依赖、IT 上下文未跟上;校验属其他 IT 职责、与 P1rContentMergeGeneratedSuggestionIT 同源)。

核心 AI 生成→runtime_call→落库断言不变(非放宽)。验证:agent 引用 3 类存在 + muse-server test-compile BUILD SUCCESS;agent 真 PG+New-API 真外部 LiveAcceptance 跑 3/3 绿(独立跑因 flyway.clean DROP 库风险未做、改以核实 diff 合理+编译+agent 报告)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 01:03:24 -07:00
lili
effb3f884b test(ci): 修全 reactor 2 个预存历史红——pay redis 配置缩进 + 覆盖报告陈旧路径(CI 单测全绿)
全 reactor 后端单测健康扫(继 knowledge 7ee9cc8 后摸清其他模块)揪出 2 预存历史红(均非本 session、自包含修复):pay 4 用例 NOAUTH——application-unit-test.yaml 的 data: 缩进 4 空格误挂 sql: 下→spring.data.redis.port=16379 失效→退默认 6379→命中本机带密码真 Redis;修=data:/redis: 回退 2 空格对齐 spring:。源自初始导入 43d6806(继承 yudao 上游)、8963383 首次全绿时 6379 无密码侥幸过。

muse-server P1rApiCoverageReportTest——p1r-api-coverage.json 16 处 completed operation 指向已删 UnavailableMetaImpactFacade.java(4bd292f 用 RealMetaImpactFacade 替换时报告未同步);修=16 处→RealMetaImpactFacade.java(替代者、JSON 合法)。验证:全 reactor mvn -o test 2834 tests 0F/0E BUILD SUCCESS;独立复跑 PayOrderServiceTest 46/0、P1rApiCoverageReportTest 8/0 真转绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:54:20 -07:00
lili
7ee9cc866e test(knowledge): 补 MuseKnowledgeBindingServiceTest 漏的 @Mock MarketHandoffTokenApi(修预存 NPE 红)
回归验证(本 session 改动确认)顺带发现的预存历史红(非本 session 引入、真实 CI 隐患):should_createMarketBindingPrecheckWithRedactedHandoffHashAndRfc3339Expiry 因测试类漏声明 MarketHandoffTokenApi 的 @Mock→@InjectMocks 注入 null→service consumeMarketHandoff 调 marketHandoffTokenApi.verify(:275)抛 NPE。该红源于 Market handoff 特性(e5d2b52/3a7a72f、6-19)补 verify/consume 真验真核销时,测试 mock 装配未跟上。

补 @Mock + 该用例 stub verify(valid=true)让 market_kb 兑现路径通过,聚焦原 precheck handoff hash 脱敏/RFC3339 过期断言不变。验证:MuseKnowledgeBindingServiceTest 11/11 全绿 BUILD SUCCESS(此前 :71 NPE 红、其他 10 用例不破坏)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:37:50 -07:00
lili
fd44d4a8bb docs(ai): 回写 SSE 长任务超时修复闭环(进度总账 + muse-module-ai/.agent 通则沉淀)
c77b006 SSE 修复后回写:进度总账 AI e2e entry 标已修闭环(A1+③);muse-module-ai/.agent 沉淀通则「SSE 长任务死线须 ≥ 上游 TOTAL_TIMEOUT + AI 流重连必须以 SSE id 幂等去重(后端 seq0 全量回放)」,避免重踩后端比上游先关门。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:54:31 -07:00
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
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
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
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
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
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
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