lili 167cedde15
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
fix(aigc-test): 修两条既存测试债——控制平面测补 MQ producer @Mock + schema 校验测夹具自包含化
条1 AigcControlPlaneTest(原 6 err):AigcTaskServiceImpl 接 RocketMQ(T-AGC-07)后新增
genTaskProducerProvider 软注入字段,本纯 Mockito 测未声明对应 @Mock → @InjectMocks 留 null →
成功入队路径(insert 后 getIfAvailable() 发 MQ 信号)6 例 NPE。补 @Mock provider(字段名同源
按名消歧)+ setUp 桩 getIfAvailable()→null(走生产「producer 缺席→跳过投递、任务留 queued」
软兜底;本测只断 insert 落库、不断 MQ 投递)。

条2 GameConfigSchemaValidatorTest(藏红/陈旧 target 假绿):accepted-configs.json 夹具由 pom
copy-wanxiang-test-fixtures 从 docs/agent-specs/2026-06-09-generation-spike 拷入,该源目录已随
史料档清理删除(6d2f8789)→ 干净构建拷空、夹具缺失、assertNotNull 红,仅靠上次构建残留 target/
陈旧副本假绿。修=从 git 史(6d2f8789^)捞回 6 条 clicker accepted 配置、落一等 test 资源
src/test/resources/wanxiang-test-fixtures/accepted-configs.json(普通 test 资源自动进 classpath)、
删已破 pom 执行段(另一拷 contracts 的执行段不动)。

验证(干净 mvn clean test 清陈旧 target/):两目标类 27/0/0;整个 aigc-server 模块套 363/0/0
Skipped 7(基础设施门测),BUILD SUCCESS,零回归。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 21:38:35 -07:00

240 lines
16 KiB
XML
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.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-aigc</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>game-module-aigc-server</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
aigc 模块业务实现:controller(app/admin) / service / dal(DO·Mapper) / convert。
生成任务异步队列 + 状态机(轮询/取消/重试);Dify/MQ/LLM 仅对接点。
被 huijing-server 聚合启动(随单体一起加载,无需独立 bootstrap)。
</description>
<!-- SAA(Spring AI Alibaba) BOM:仅管 SAA/spring-ai 制品版本;不引 spring-boot-dependencies,Boot/Redisson 以 huijing-dependencies 为准(保住 3.5.14/4.4.0) -->
<dependencyManagement>
<dependencies>
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>1.1.2</version><type>pom</type><scope>import</scope></dependency>
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-bom</artifactId><version>1.1.2.2</version><type>pom</type><scope>import</scope></dependency>
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-extensions-bom</artifactId><version>1.1.2.2</version><type>pom</type><scope>import</scope></dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- ===== SAA(Spring AI Alibaba) agentic 编排框架 · 实际证成依赖集(HJ-AGI-002;版本随上方三 BOM) =====
经迁移 step2(模型节点)+step5(MysqlSaver checkpoint)+observation 接线后,逐个证成在用的最小集:
· graph-core —— 图引擎 StateGraph/Node/Edge/CompileConfig + **MysqlSaver(checkpoint 权威 saver,
类在 com.alibaba.cloud.ai.graph.checkpoint.savers.mysql)** + **observation 埋点机芯
(GraphObservationLifecycleListener/GraphNodeObservationHandler 均在本 jar)**。唯一必需。
· starter-graph-observation —— 仅 Spring Boot 自动配置层(GraphObservationAutoConfiguration):把上面
graph-core 的 observation 机芯自动装配进上下文(per-node trace/耗时/token/guard 失败可观测)。
· spring-ai-starter-model-openai —— 上游模型三件套(OpenAiApi/OpenAiChatModel),baseUrl 指 new-api。
【DECISION · agent-framework / builtin-nodes 已移除(2026-06-16,见 目标架构 review §10)】
· agent-framework(ReactAgent/asNode/FlowAgent.subAgents)—— 当前生产用「裸 StateGraph + 自定义 NodeAction
+ 条件边回环 + state 计数器」的确定性多步编排(dossier §0-1),全程零引用;且 asNode 经源码证伪绑
agentscope-core 1.0.9(§10 P0-1)。**ReactAgent/asNode 延 Phase1.5(Tier-3 自治组有真实首个消费者 ∧
MVP 闭环已上线 才触发),届时再引 agent-framework**。现移除以收窄依赖面、消除未用传递依赖。
· builtin-nodes(AnswerNode/HttpNode/McpNode/code 执行等内置节点)—— 零引用,且硬钉 1.1.2.2 脱 BOM,
还传递拖入 tika 全家桶(document-parser-tika + 数十个解析器,~75 行子树)+docker-java,纯负担,移除。 -->
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-graph-core</artifactId></dependency>
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-graph-observation</artifactId></dependency>
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-openai</artifactId></dependency>
<!-- Anthropic 协议客户端(Plan A · U1 M3 client;版本由上方 spring-ai-bom:1.1.2 托管,勿写 version)。
刻意用 bare `spring-ai-anthropic`(裸库,非 `-starter`):仅要 AnthropicApi/AnthropicChatModel/AnthropicChatOptions
这套低层 API,避免 `-starter` 的 AnthropicAutoConfiguration 在 Spring 上下文里抢注 ChatModel bean(与现有
OpenAI 路并存时会冲突)。U1 client 经 new-api **host 根 /v1/messages**(baseUrl=host 根、x-api-key 鉴权;
lili-mac spike 1.1.2 实测纠偏:**绝不加 /anthropic 前缀**,否则命中 SPA catch-all 返 HTML 假挂起)驱动
MiniMax-M3 走 Anthropic Messages 协议(thinking 原生分离),与 OpenAI-兼容路 flag 旁挂。 -->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-anthropic</artifactId></dependency>
<!-- ===== Sentinel 入口 QPS 突发保护(切片一 阶段〇 C2)=====
· spring-cloud-starter-alibaba-sentinel:@SentinelResource 切面 + 流控运行时(SentinelResourceAspect 自动装配);
· sentinel-datasource-nacos:流控规则从 Nacos dataId sentinel-gen-flow-rules 热加载(改即生效、不重启)。
版本由 huijing-dependencies 的 spring-cloud-alibaba-dependencies:2025.0.0.0 BOM 托管(实际 Sentinel 1.8.9),不写死。
职责 = 生成入队入口速率闸(FLOW_GRADE_QPS 削洪峰),与 DB 三门(业务配额)/ C3 consumeThreadMax(dispatch 投递速率上限;真在跑并发≤15 属有界 worker 池=follow-up)三层正交。 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- Spring Cloud 基础环境 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-env</artifactId>
</dependency>
<!-- 本模块对外契约层 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-aigc-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 回调落包链依赖 project 的 -api:createForPackage 建版本拿 versionId(跨模块只依赖对方 -api,禁依赖 -server,守门④;HJ-AGENT-LOOP-EXEC-001 §8.2) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-project-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 依赖 community 的 -api:P-NTF-02 生成完成后同进程 notify 站内信(Wave4 挂点1;事务提交后调 + try-catch 吞异常,禁依赖 -server) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-community-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 依赖 studio 的 -api:源项目落库 seam(U2/B8 §5.2 源落库事务)。源项目工件归属 studio(编排层,§12-①),
aigc 回调链在「源 JSON 可得(图终态)+ versionId 已生(建包后)」两处 best-effort 调 SourceProjectApi 落源/回填/标孤儿。
跨模块只依赖对方 -api(守门④);本依赖无环:studio-api 不反依赖 aigc(仅 studio-server→aigc-api 单向)。 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-studio-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 回调落包链依赖 runtime 的 -api:storeForVersion 建运行包行 + 写整包 manifest(跨模块只依赖对方 -api,禁依赖 -server,守门④;HJ-AGENT-LOOP-EXEC-001 §8.2) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-runtime-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 依赖 system 的 -api:直发生成入口校验创作者白名单(PlayerApi#validateCreator,2026-06-10 鉴权件 §6.3,拍板4 可信边界) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 依赖 infra 的 -api:D12 控制平面降级开关走 infra ConfigApi(aigc.generate.paused,admin 后台可热改、无需重启;
W-G1 组A · 执行版 §6.1)。additive 依赖,不影响现有编译/运行,仅为 ConfigApi 注入。 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-module-infra-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件:数据权限(创作者只见自己任务)+ 多租户(DO 继承 TenantBaseDO) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-biz-data-permission</artifactId>
</dependency>
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- RocketMQ(切片一 阶段〇 C3:异步 gen 队列 生产者+有界并发派发消费者 consumeThreadMax=15):RocketMQTemplate / @RocketMQMessageListener。
starter-mq / starter-websocket 均以 optional=true 声明本 starter(不传递),故本模块须显式直依赖;版本由 huijing 依赖管理统一控制。 -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
<!-- Web + 安全:@RestController / @PreAuthorize / 当前登录用户 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB:MyBatis Plus(BaseMapperX / LambdaQueryWrapperX / BaseDO) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- JSON Schema 校验(HJ-AGENT-LOOP-EXEC-002 §7 / §16-3 已批准):生成执行器按 contracts/templates/
clicker.schema.json 同源校验 LLM 直出 GameConfig(注入 prompt 的 schema 文本与服务端校验对象
字面同源,零逻辑分叉;替代手写校验防双源漂移)。运行时仅依赖 Jackson/slf4j,均已在 classpath。
版本由 huijing-dependencies 统一管理。 -->
<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-redis</artifactId>
</dependency>
<!-- RPC 远程调用(跨模块互调,预留回写 project.game_version、对接 runtime/feed) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-rpc</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 契约资源构建期快照(HJ-AGENT-LOOP-EXEC-002 §6.1 方案 A):把 contracts 两文件复制进
classpath:wanxiang-contracts/——git contracts/ 仍是唯一事实源,jar 内只是构建时快照;
改 prompt = 改 contracts 原文件 + 升 version + 过四道闸 → 下次构建部署自动携带新版。
已知坑:maven 对不存在的 resource 目录静默跳过(不报错)——若未来拆独立仓致相对路径失效,
兜底 = 执行器启动自检(PromptResourceLoader:资源缺失自禁用 + log.error,永不带病认领)。 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<!-- 显式钉版本:消除 effective model 告警,并保证快照复制行为不随 Maven 发行版默认值漂移 -->
<version>3.3.1</version>
<executions>
<!-- 主 classpath 快照:执行器运行时读取(test classpath 含主输出目录,单测对拍同此快照) -->
<execution>
<id>copy-wanxiang-contracts</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/wanxiang-contracts</outputDirectory>
<resources>
<resource>
<!-- 仓库根 contracts/(aigc-server → game-module-aigc → game-cloud → 仓库根) -->
<directory>${project.basedir}/../../../contracts</directory>
<!-- HJ-MC-TPL-EXEC-001 §6.2:通配复制各模板 designer prompt + schema(clicker/merge/批② idle/tycoon),
一次性覆盖未来新模板,免每模板手改 pom(兑现「加文件即开模板」承诺)。
此前仅复制 clicker 两单文件,merge 两文件不会自动进 classpath → merge 自禁用,必须改通配。 -->
<includes>
<!-- W-G1 组A · GP9(执行版 §6.2):01-safety prompt 进 classpath,
服务层独立 safety 客户端据此装载 prompt-safety-check.md(单变量 {{input.prompt}})。 -->
<include>prompts/01-safety/*.md</include>
<include>prompts/04-config/*.md</include>
<include>templates/*.schema.json</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<!-- 测试夹具(C1 spike 实测通过的 6 条 accepted configs,供 GameConfigSchemaValidatorTest 全过断言,
HJ-AGENT-LOOP-EXEC-002 §11)已于 2026-07-04 落为一等 test 资源
src/test/resources/wanxiang-test-fixtures/accepted-configs.json:原 copy-wanxiang-test-fixtures
执行段的源目录 docs/agent-specs/2026-06-09-generation-spike 已随史料档清理删除(6d2f8789),
构建期拷贝拷空 → 干净构建夹具缺失、仅靠陈旧 target/ 假绿;改由普通 test 资源自动进 classpath,删除该执行段。 -->
</executions>
</plugin>
</plugins>
</build>
</project>