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>
This commit is contained in:
lili 2026-06-26 01:03:24 -07:00
parent 79674ff31d
commit a0569c6481

View File

@ -10,7 +10,9 @@ import cn.iocoder.muse.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.muse.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.muse.framework.tenant.core.util.TenantUtils;
import cn.iocoder.muse.module.ai.application.muse.MuseAiAuditServiceImpl;
import cn.iocoder.muse.module.ai.application.muse.MuseAiCandidateReviewService;
import cn.iocoder.muse.module.ai.application.muse.MuseAiCommandServiceImpl;
import cn.iocoder.muse.module.ai.application.muse.MuseAiEventPublishOutboxService;
import cn.iocoder.muse.module.ai.application.muse.MuseAiRuntimeCallRecorder;
import cn.iocoder.muse.module.ai.application.muse.MuseAiRuntimeJobExecutor;
import cn.iocoder.muse.module.ai.application.muse.MuseAiRuntimePayloadStore;
@ -19,6 +21,7 @@ import cn.iocoder.muse.module.ai.application.muse.MuseAiRuntimeProjectionService
import cn.iocoder.muse.module.ai.application.muse.MuseAiRuntimeServiceImpl;
import cn.iocoder.muse.module.ai.application.muse.MuseAiTaskService;
import cn.iocoder.muse.module.ai.application.muse.MuseAiTaskServiceImpl;
import cn.iocoder.muse.module.ai.application.muse.facade.KnowledgeRetrievalFacade;
import cn.iocoder.muse.module.ai.application.muse.facade.MuseAiRuntimeClient;
import cn.iocoder.muse.module.ai.application.muse.facade.MuseContentWorkOwnerFacade;
import cn.iocoder.muse.module.ai.application.muse.facade.RealNewApiMuseAiRuntimeClient;
@ -110,7 +113,9 @@ class P1rAiRuntimeEndToEndLiveAcceptanceIT {
private static final String FLYWAY_LOCATION_PROPERTY = "p1r.flyway.locations";
private static final String POSTGRESQL_JDBC_PREFIX = "jdbc:postgresql://";
private static final String JDBC_URI_PREFIX = "jdbc:";
private static final String TARGET_VERSION = "13";
// 必须迁到当前最高版本 V31:V30 muse_ai_suggestion.authorization_snapshot_id BIGINT 加宽为 VARCHAR(128)
// 以承载字符串 runtime permission envelope(ADR-020);若停在旧版本,投影写字符串授权快照会触发 bigint 类型不匹配
private static final String TARGET_VERSION = "31";
// 固定 test-only AES 密钥 EncryptTypeHandler 写入 live payload 时读取不从用户环境变量取值
private static final String TEST_ENCRYPTOR_PASSWORD = "p1rLiveEncrypt16";
private static final Long TENANT_ID = 100L;
@ -465,7 +470,7 @@ class P1rAiRuntimeEndToEndLiveAcceptanceIT {
flyway.migrate();
MigrationInfo current = flyway.info().current();
assertEquals(TARGET_VERSION, Objects.requireNonNull(current, "必须存在当前 Flyway 版本")
.getVersion().getVersion(), "P1R-4 AI runtime live acceptance 至少需要 V13 schema");
.getVersion().getVersion(), "P1R-4 AI runtime live acceptance 需迁到 V31 schema(含 V30 授权快照列 BIGINT→VARCHAR)");
return dbEngine;
}
@ -957,6 +962,7 @@ class P1rAiRuntimeEndToEndLiveAcceptanceIT {
MuseAiRuntimeJobExecutor.class,
MuseAiRuntimeCallRecorder.class,
MuseAiRuntimeProjectionService.class,
MuseAiCandidateReviewService.class,
MuseAiRuntimeServiceImpl.class,
MuseAiRuntimePolicyProvider.class,
MuseAiRuntimePayloadStore.class,
@ -965,6 +971,29 @@ class P1rAiRuntimeEndToEndLiveAcceptanceIT {
})
static class LiveAcceptanceConfiguration {
/**
* 运行时投影服务 {@link MuseAiRuntimeProjectionService} 通过 {@code @Resource} 强依赖事件投递 outbox 服务
* live-acceptance 仅断言 muse_ai_generation/job/runtime_call/task_event 等核心落库,不校验 outbox ,
* 故提供空实现满足 bean 注入即可( {@code P1rContentMergeGeneratedSuggestionIT} 同源做法),
* 不引入真实 impl 以免把 outbox mapper 事务语义牵入本上下文
*/
@Bean
MuseAiEventPublishOutboxService museAiEventPublishOutboxService() {
return event -> {
};
}
/**
* 运行时 job executor 通过 {@code @Resource} 强依赖知识检索 facade(P-A/P-C 检索串联引入)
* live-acceptance 只验证 AI 生成runtime_call落库主链,不校验知识检索上下文(那是
* {@code P1rKnowledgeRuntimeEndToEndLiveAcceptanceIT} 的职责),故返回 facade 契约自带的
* 无命中/降级空上下文({@link KnowledgeRetrievalFacade.ContextAssembly#empty}),executor 设计上对此幂等放行
*/
@Bean
KnowledgeRetrievalFacade knowledgeRetrievalFacade() {
return request -> KnowledgeRetrievalFacade.ContextAssembly.empty("p1r-live-ai-runtime-skip-retrieval");
}
@Bean
MuseAiProperties museAiProperties() {
MuseAiProperties properties = new MuseAiProperties();