lili 3585219637
Some checks failed
Backend Maven CI / backend-local (push) Has been cancelled
feat(mvp): 收束1.0.0线A交付闭环
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 10:52:10 -07:00

13 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# .agent — muse-module-ai(AI 编排 BC)
> 模块跨会话记忆。真实现状权威见 [现状基线 §5.1](../../docs/agent-specs/2026-06-13-项目目标与模块现状基线.md);进度见 [总账](../../docs/mvp/进度总账.md)。本文件只记目标/边界/out-of-scope/现状指针/TODO,过时即更。
- **目标(owner 职责)**:链路编排 / 上下文组装 / 生成 / 分析 / 全书解析 / 质量门控 / AI 候选(Suggestion)/ 规划候选 / 风险标记 / Quality Result / 运行记录;承载 Protection Node(grant)与 Quality Policy。
- **边界(不可违反)**:**只产 Shadow,绝不直写 Canonical**;只消费服务端签发的 Runtime Permission Envelope,不能自授权;runtime/任务执行侧不得直连 `ToolGrant` 写模型(`AiGrantRuntimeBoundaryArchTest` 最小门禁已守住);grant 与 runtime 完整物理包隔离仍后置;守 BC 边界不碰他域 `.dal`([bc-boundaries](../../.agents/rules/bc-boundaries.md);历史违例 `ContentMuseWorkOwnerFacade` **已整改消除**——改消费 content `MuseContentWorkOwnerApi`,门禁已收紧、无豁免)。
- **out-of-scope**:Accept Suggestion(归 content BC)、正文写入。
- **现状**:只读评估 80%;后端真实较高质量(无 stub),`RealNewApiMuseAiRuntimeClient` 真打 New-API,SSE 已脱占位;studio `/agents` 已补自建智能体生命周期活体证(2026-06-27:`agent-create.spec.ts` MSW-off 真单体 1/1,覆盖创建初始版本、编辑生成 v2、版本切换、归档非当前版本、归档 AgentDB 证 `current_version_id` 与版本 status)。
- **E4 market agent 物化(2026-06-27)**:market agent handoff 不再信任客户端 `sourceAgentId/sourceAgentVersion`;AI 目标 owner 按 market asset `source_id` 解析发布者 agent并物化为安装者本地 user agent槽位绑定指向本地副本。MSW-off Playwright `handoff-agent.spec.ts` 2/0F/0E正路物化后真实创建 AI task 并完成 New-API runtime负路伪造 token 被拒。注意e2e 前置种入 Security 已批准 runtime grant生产 runtime 不自授权。
- **E5 account 用量/配额接线(2026-06-27)**:AI task 创建前经 Account owner 预占配额,成功投影时记录 usage 并累加 quota used,非可重试失败终态释放预占;AI 只消费 member-api 端口,不碰 member DAL。`P1rAiRuntimeEndToEndLiveAcceptanceIT` 显式 live 3/0F/0E/0S,反查 Account usage record=1、quota used=1、reserve audit=1、release audit=0、attribution job/item completed。targeted AI 单测中 `MuseAiTaskServiceTest` 40/0F/0E、`MuseAiRuntimeProjectionServiceTest` 6/0F/0E。
- **E6 admin AI 配置接线(2026-06-27)**:Muse Admin AI 配置页 Prompt 激活、质量评估启动、质量策略版本创建已调用真实 admin API不再展示硬编码评估分数未接后端的 Agent/Tool Grant/rollback 类命令仍保持 preview-only不计为真写。验证:`muse-admin` AI 配置 Vitest 50 files / 347 tests passed`@vben/web-antd typecheck` 通过。
- **关键风险 / TODO**:**AI runtime 生成 e2e 已端到端真验(2026-06-24)**——方案1(d647f0c 剥离 sourceSnapshotId 解授权死结)+ D(4dadc7b `DefaultDBFieldHandler` 无登录兜底 `system`,根治 scheduled worker 写 creator/updater null 违约 NOT NULL;BaseDO 带 jdbcType 强制入列致 insert/update 同病)+ agent_version config 补 modelKey=MiniMax-M2.5 + 启动 source `scripts/dev/p1r-external-acceptance.env`(New-API/RAGFlow 配置)→ task5 completed+suggestion+MiniMax-M2.5 真 LLM 生成(P-B envelope/approved、P-C contextAssembly 固化 ✓)。**P-A/P-B/P-C 完整 e2e 已端到端真验打通(2026-06-24,task7)**:P-A 检索命中根因=knowledge 模块 bug——`HttpRagFlowKnowledgeRuntimeClient.retrieveChunks` 把 `document_ids` 以 null 入 retrieval body,RAGFlow 要求其为 list 故拒(code 102 "documents should be a list")→检索 fail-closed→chunkCount=0(task3/4/5/6 全 0 即此 bug,非 RAGFlow 数据/凭据/timeout)。已修(commit 86c6dba:null 时不入 body + 回归测试)。task7 contextAssembly `chunkCount=1/retrievedKbIds=[2]/authorizationSnapshotIds=[authsnap-e2e-1]`,LLM(MiniMax-M2.5)基于 grounding 续写。**02D 槽位首次创建死锁已修+真验(2026-06-24,commit 9115d4f)**:根因=precheck/bind 都 `requireSlotBinding`(缺行抛 forbidden),而"替换"是设计中唯一创建入口("替换"=首次写入、无独立创建端点是设计有意,见后端-04 line748/产品-02D line507)→死锁,首次绑定永不可达(work4 seed binding 实为 E2E 绕此 bug 手插)。修:precheck 缺行放行 + bind 抽 `persistBinding` upsert(无行 insert revision=1/有行 updateById 沿用乐观锁)+ V29 `uk_muse_agent_slot_binding_active` partial unique index(同 work+slot 仅一条 active 并发兜底)+ 前端 mock protected 口径对齐 `protected:` 前缀。真验(muse_slice_live):work1 `writing.continuation` precheck(不再 forbidden)→bind 首次建 binding(slotRevision=1 active)→GET 槽位显示 agent1→AI task 用 `agentSlotKey`(非 agentOverrideRef)→agent1 解析 + runtime 授权过门 → completed + suggestion7(MiniMax-M2.5 真 LLM"星环大陆魔法体系"续写、finishReason stop)。**前端 MVP(df063cb)agentSlotKey 路径真后端端到端走通**;单测 `MuseAgentSlotServiceTest` 26/26 + Controller 4/4 + 前端 4/4;V29 由 Flyway 启动日志证 applied。**E2 智能体生命周期与候选拒绝已补并真验(2026-06-27)**:用户自建 Agent create 会同步建 v1 active version;update 创建下一 active version 并更新 `current_version_id`;版本面板支持 list/activate/archive 非当前版本;archive Agent 同步 archive active 槽位绑定;slot unbind 将 binding revision+1、status=`archived`、响应 `sourceStatus=unbound`;WorkspacePage reject 调 AI owner `POST /suggestions/{id}/reject` 写 `rejected` 与 decision archive。验证:AI targeted 单测+Controller 63/0F/0E,Studio `tsc`/目标 ESLint/targeted Vitest 29/0F/0E,MSW-off Playwright 真后端 5/0F/0E(采纳真生成 suggestionId=80、拒绝真生成 suggestionId=81、Agent 生命周期 DB 核验、Slot unbind DB 核验)。**仍缺/线 B**:Override Slot Contract 主数据(方案 B:合法 slot 校验/系统默认 agent/listWorkAgentSlots 预设骨架未做,slotKey 暂自由字符串、listSlots 缺行仅返回已绑定);前端 agent "运行试用"等深链;质量评测执行器只到 eval-run 入队,未计入 1.0.0 线 A done;grant/runtime 完整物理包拆分仍未做。SSE `event:` 解析漂移已修复并有 targeted Vitest 证据(2026-06-19:`sse.test.ts` + `AIPanel.contract.test.tsx` 17/17);`muse-module-ai-contract-server` 空壳孤儿 submodule 已清理(2026-06-19:从 AI reactor 移除并删除唯一 pom,`P1rAiRouteOwnershipTest` 加回潮门禁)。**2026-06-25:AI 生成候选采纳断层已修(ADR-020 方案 A,commit a16c596)**——`MuseAiRuntimeProjectionService` 此前用 `numericEnvelopeId(Long.parseLong)` 落 authz 快照,但真 runtime envelope 是字符串 `rpe-local-uuid`→解析失败落 null→suggestion 恒不可采纳(merge 1041001001);改直落字符串 envelope(删 numericEnvelopeId)、`MuseAiSuggestionDO.authorizationSnapshotId` 改 String、`AiSuggestionMergeProjectionFacade.getSuggestion` 校验改 hasText、V30 列 BIGINT→VARCHAR(128)。揭 `P1rContentMergeGeneratedSuggestionIT` 假绿(注入数值 9001、真 runtime 不产数值),改真字符串 envelope 转真绿。活体真验:真生成 suggestion authz=rpe-local 字符串→采纳 merge code=0+block revision 自增,生成→采纳→Canonical 全链通。详见总账 2026-06-25 / ADR-020 / memory muse-ai-accept-authz-snapshot-fix。**2026-06-27:E1 accepted decision owner 归档已补**——`AiSuggestionMergeProjectionFacade.markSuggestionAccepted` 作为 AI owner 写 `muse_ai_suggestion_decision`、更新 suggestion `status=accepted/decision_archive_id`、记录 AI command 与 business audit幂等 replay 不重复写,非 pending 候选返回 conflict 且不预占 command。注意边界:AI 仍只归档 Shadow 决策与审计,不写 Canonical 正文,不保存 `finalContent` 或 provider 原文。P1r 真 PG 切片 6/0F/0E/0S。**2026-06-25(同日续):槽位绑定授权快照孪生收口(C1,commit 854f18c)**——三路盘点发现 `muse_agent_slot_binding.authorization_snapshot_id` 是采纳断层唯一漏网 binding 表(列 BIGINT、DO Long,bind 时 parseLong 对字符串 envelope `rpe-local-<uuid>` 返 null→授权快照静默丢失、绑定溯源链断);V31 两列(authz+source)BIGINT→VARCHAR(128)、DO Long→String、bind 两处(insert/updateById)直透传删 parseLong(`sameAuthorizationSnapshot` 的 parseLong 保留,字符串 envelope 走 fallback 字符串比较正确)。活体真验(muse_slice_live):真 envelope 经 precheck→bind,binding authz 列存非空 rpe-local(insert id=51+updateById id=50 两路径),列类型 varchar(128)、flyway V31 success;修前恒 null。**此前模块"仍缺"只列方案 B/深链/物理拆分,从未记此类型错配——盘点补上的盲区**。至此 ADR-020 全部 binding 表(knowledge V14 + suggestion/attribution V30 + slot V31)收口完成。 **2026-06-25(同日续):AI 流 SSE 长任务候选丢失已修(commit c77b006、A1+候选③、design-docs/临时-01 review 批准后执行)**——studio e2e ai-generation 真红根因=后端 `MuseAiTaskStreamServiceImpl` SSE 死线 30s 硬编码 < LLM 真时延(MiniMax 11-60s)、更 < 上游自己 `MUSE_AI_NEW_API_TOTAL_TIMEOUT_SECONDS=180`,poll 30s 后 `emitter.complete()` 静默关连接不补 done;前端 `connectAIStream` 一次性连接无重连(重连只在 connectEventStream)→LLM>30s 候选永丢(ai-gen 真红/accept flaky 是同 bug 时延两侧)。修:① 后端删 `DEFAULT_TIMEOUT_MILLIS` 常量→`@Value("${muse.ai.sse.task-timeout-millis:240000}")`(连接死线:70+poll deadline:198 同引用、application.yaml 配置项);② 前端退避重连续 poll + 按 SSE id 去重(后端不读 lastEventId、每次 seq0 全量回放→`lastSeenSequenceNo` 丢弃 id≤已见,避免重复渲染候选)+总超时 300s `onError(SSE_TIMEOUT)` 不静默卡死(返回仍 AbortController、AIPanel 零改动);③ A1 `scripts/dev/start-muse-server-infra.sh` 固化追加 source acceptance env(防漏 `MUSE_AI_NEW_API_*`→`UnavailableMuseAiRuntimeClient` 兜底秒失败 `AI_NEW_API_UNAVAILABLE`)。验证:后端 SSE 单测 14/14+前端 107/107(含重连去重用例)、活体 e2e ai-generation+accept 连跑 3 轮 6/6、重连幂等方法 A 活体证;残留=本机 LLM 6.8-19s 未自然>30s、慢路径靠「240s 数学覆盖上游 180s+单测+方法 A 重连活体证」三重保证。**通则(避免重踩"后端比上游先关门")**:SSE 长任务死线须 ≥ 上游 TOTAL_TIMEOUT;AI 流重连必须以 SSE id 幂等去重(后端 seq0 全量回放、无 lastEventId)。详见 memory muse-ai-generation-sse-timeout-bug。