games-development-ai/docs/agent-specs/2026-07-02-配置控制面阶段二-yudao配置中心-设计.md
lili 8409f19c2a
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
docs(svg): 配置控制面阶段二 4 张人读 SVG(W-DSGN SVG 尾波核心)+ 接入阶段二设计档填占位
opus 按 atlas 标准产 4 图落 docs/agent-specs/assets/,fable 终审(结构良构+viewBox 自适应/最复杂的双路激活图
qlmanage 渲 PNG 亲看无溢出配色准/设计档 diff 零 prose 改):
- cfgctl2-01 配置中心分层与分工(yudao 治理⊕Nacos 路B、基建vs业务分工、prompt 出 Nacos 进 MySQL)
- cfgctl2-02 双路激活编排(sanity 前置→beginActivating 快照→路A PATCH∥路B publish→markVersionActivated→补偿)
- cfgctl2-03 激活一致性状态机(草稿→待审→ACTIVATING V30 持久态→已激活;recoverActivating 幂等/双恢复语义)
- cfgctl2-04 漂移对账三态(IN_SYNC/DRIFT/不可达;8s 容忍窗;篡改→检出→重推→收敛闭环)
接入阶段二设计档 §2/§3.2/§3.3/§3.6 四处 SVG 占位为真实内嵌+图清单同步(11增8删,零 prose 改)。
atlas 复验全过(界内/良构/脚注/转义)、docs-gate 绿。W-DSGN 只剩旧档 SVG(plan①顶图/quality/重推演,非阻塞)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 01:43:41 -07:00

301 lines
48 KiB
Markdown
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.

---
date: 2026-07-02
topic: 配置控制面-阶段二
status: 已实施(2026-07-04,fable 编排·opus 执行·逐波终审)· 创始人已拍方向 B(维持 yudao⊕Nacos;prompt 移出 Nacos→MySQL 版本行,2026-07-02)· Codex+Opus 双评审 11 条已回并全修收口(2026-07-02)
sot-impact: 修订 生成引擎运行时(SoT §5.2 管理面配置管理 / §5.8 配置三类"受治理发版" / ADR-4 配置热取 / A13 配置注册表:把 GitOps/Langfuse 式口径收敛为 yudao 配置中心版本化(版本账本落 MySQL 版本行)+ 双路激活,与上级设计 §6 pending 同一收口面,已回写(2026-07-03,W-DSGN doc-sync);对上级设计四处口径 + SoT 回写的回调挂账见本档 §7)
上级: docs/agent-specs/2026-06-30-配置控制面一次性按序实现-设计.md
关联:
- 阶段前置(已落地):阶段〇 生产基建(Nacos 2.4.3 / RocketMQ 5.3.1 / Sentinel 自托管 mini-infra + game-cloud 接入,`docs/plans/2026-07-01-配置控制面-spike与阶段生产基建-plan.md`)· 阶段一① 护城河 middleware(实施 plan 档 `07100eef`;代码落地 = feat 提交 `55162341`/`e9c7a3bb`/`c2661719`,统一门判 GateJudgment + 续修 RepairMiddleware + 软预算软停)· 阶段一② cheap-worker 归并 Service `/chat`(实施 plan 档 `526e9b3d`;代码落地 = feat 提交 `e9e7006c`/`1662eb0d`,九门判据 run_cheap_gates + 独立 Service 壳 build_cheap_app)
- tier2/gen-worker/worker/genconfig.py(进程内配置门面 `get(area,key,default)`,现读本地 `tier2/config/generation.yaml`;本阶段把其读取后端提升到 Nacos)
- tier2/gen-worker/worker/nacos_hotconfig.py(阶段〇 D2 已建、未接线;本阶段接进 genconfig 作热源)
- tier2/gen-worker/worker/middleware.py:173(CircuitBreakerMiddleware 软预算,预算/阈值经 genconfig 读)· worker/gate_judge.py(门判 GateJudgment)
- tier2/gen-worker/worker/store.py(成品源工程归档的后端 seam:BackendStore 定义 MySQL manifest + MinIO 源文件接口、当前为占位,真正在用的是 LocalFsStore 本地实现 —— §3.1 prompt 存储选型佐证)· cheap-worker/cheap_roles.py 30499B(≈30KB)/ tier2 worker/roles.py 24539B(≈24KB)/ contracts/prompts/04-config/cheap-system.md 14695B(≈14.7KB,外置 prompt 最大单条)(prompt 尺寸画像依据)
- cheap-worker/cheap_service_app.py:213(`_cheap_middlewares_factory` 每回合工厂)· :300(`build_cheap_app`)
- tier2/gen-worker/service/app.py(AgentScope Service `/chat` + `/agent` + `/sessions`)
- agentscope==2.0.2:app/_router/_agent.py:138(`update_agent` PATCH)· app/_router/_session.py:291(`update_session` PATCH,部分字段更新语义)
- game-cloud huijing-module-bpm(审批,放量后)· huijing-module-system(操作日志 + 权限,yudao 原生)· game-module-aigc(生成配置治理落点)· huijing-module-infra(Nacos SCA 通路 + infra_config KV 参照)
- game-admin/src/views/wanxiang(配置编辑面,阶段三消费)
- commit hash:待收口填
图清单: [图0 一图看懂(待补), 图1 配置中心分层与分工, 图2 双路激活编排, 图3 激活一致性状态机, 图4 漂移对账三态]
---
# 配置控制面 · 阶段二:yudao 配置中心 · 功能设计
## 0 一图看懂
(图0 概览 SVG 待补)
- **核心思想**:阶段一已经让生成配置能热改——prompt/模型/参数经 `/agent`+`/sessions` 由 AgentScope 每 POST 现装配、下一次生成即生效,预算/门阈值经 genconfig 从本地 YAML 热取。但热改缺一层治理:改动没有版本历史、没有归因、不能一键回滚、没有激活闸。阶段二在这层热配之上补一个**版本化治理层**:创始人在 game-cloud 的 yudao 侧编辑一组生成配置,走"改 → 定版 → 审核挂点 → 激活",激活时**双路下发**——prompt/模型/参数这一路 PATCH 进 AgentScope Service(写它的 Redis,下一次 POST 现装配即生效),预算/门阈值这一路 publish 进 Nacos、由 worker 的 genconfig 经 Nacos 热读投影。版本历史、回滚、diff 落 yudao 侧的 MySQL 版本行(prompt 正文随行存 `MEDIUMTEXT`、**不进 Nacos**——Nacos 单配置默认上限 100KB,扛不住会长大的 prompt,创始人已拍);Nacos 收窄为预算/门阈值那一路的生效下发通道;鉴权、creator 归属、审计、审批全部复用 yudao 原生。
- **边界**:管**业务生成配置**的版本化治理(prompt/context/max_iters/模型/参数/预算/门阈值);**基建配置**(game-cloud 的 Spring 配置、Sentinel 流控规则、RocketMQ 参数)不进本治理层——那条是阶段〇已接的 Nacos SCA 原生通路,运维改、即时热生效。BPM 审批**放量后启用**(架构预留挂点,MVP 由创始人本人直接激活);配置编辑 UI 属阶段三;观测属阶段四;机制级激活原子性留放量后(MVP 取静默期语义)。
- **成功**:本会话手改过的每个旋钮(模型 M3↔glm-5.2、预算 ¥10↔¥49、max_tokens、prompt)都能在配置中心改一版、激活、下一次生成即生效、一键回滚,并可查谁在何时改了什么、diff 是什么;一组协同旋钮作一个配置集一次激活;激活失败、Service 不可达、配置漂移都有明确兜底。
## 1 意图与目标
### 1.1 意图
配置控制面这条线的痛点在上级设计里已经讲透:本会话调一款便宜档游戏,四个旋钮里三个要改代码重启,而且是在 live worktree 上 SSH 手敲。阶段〇到阶段一②把"能不能热改"这半解决了——生产基建三件套自托管进 mini-infra,护城河续修/软预算/门判做成 AgentScope 洋葱里的 middleware,cheap 与 tier2 两档都归并到同一套 Service `/chat`,prompt/模型/参数经 `/agent`+`/sessions` 每 POST 现装配、预算/门阈值经 genconfig 从 `generation.yaml` 热取。
剩下的是"改动能不能管"这半。今天改一个旋钮,要么直接 PATCH Service、要么 scp 一份新的 `generation.yaml` 上去,两条路都没有版本账本:改错了没有上一版可回滚,改过了查不出是谁在什么时候改的、和上一版差在哪,更没有一个"激活"的闸把"编辑中"和"已生效"分开。放量后这些配置要过审批才能上生产,现在连挂审批的地方都没有。阶段二就是把这层治理补上,让配置从"能热改的散落旋钮"变成"可版本、可回滚、可归因、可审批的受治理资产"。
还有一个阶段〇留下的 follow-up 一直悬着:`nacos_hotconfig.py` 在阶段〇 D2 已经写好并单测绿了,但没有接进任何 middleware——预算/门阈值现在还是 genconfig 从本地文件读。这条线不接上,配置中心对预算/阈值那一路的"激活"就落不了地。阶段二把它接上,让这些参数真正从 Nacos 热读,从"本地文件热取"升级为"配置中心版本化 + 集中热推"。
### 1.2 目标
- **配置即数据、版本可管**:每一组生成配置进配置中心,能改一版、激活、回滚、看 diff,逐项覆盖本会话手改过的全部硬编码点。
- **改动可审计、归因到人**:编辑者即 yudao 登录用户、落进 `creator`,写操作受权限门约束,每次改动与激活随版本可查,审计复用 yudao 原生操作日志。
- **双路激活、以激活版为权威**:prompt/模型/参数经 PATCH、预算/门阈值经 Nacos 热读,两路由同一个激活编排统一驱动;配置中心记"当前激活版"为权威,Service 与 worker 是它的生效投影。
- **NacosHotConfig 接线落地**:genconfig 的读取后端从本地 `generation.yaml` 提升到 Nacos(NacosHotConfig 作热源、本地 YAML 与内置默认作回落),middleware 的调用面一行不改。
- **分工边界清晰**:基建配置走 Nacos SCA 原生通路、不经本治理层;业务生成配置以 yudao 为治理与版本账本、只以 Nacos 作路 B 生效下发;两者在 Nacos 上以命名空间/分组隔离。
- **失败模式有兜底**:激活是一批非原子写,须幂等、失败即整批判未生效可重试;Service 不可达时保留上一激活版;配置漂移可检测并一键重推。
## 2 边界
![图 1 · 配置中心分层与分工](assets/cfgctl2-01-配置中心分层与分工.svg)
进控制面的判据沿用 SoT §5.8 的配置三类;本阶段只碰其中"热配置策略类"里属于**生成业务**的那部分,并给它加治理。
| | 进阶段二 | 不进 |
|---|---|---|
| **业务生成配置**(受治理版本化) | prompt / system_prompt、压缩比例、tool_result 截断、max_iters、模型、协议 type、credential 引用、max_tokens、thinking、reasoning_effort、temperature、软预算目标、门阈值档 | — |
| **基建配置** | — | game-cloud Spring 配置、Sentinel 流控规则、RocketMQ 参数、服务发现——阶段〇已接 Nacos SCA 原生通路,运维改、即时热生效 |
| **硬代码机制类** | — | 门断言逻辑、熔断机制本体、续修机制、基线硬门强制、那几条铁律 |
几条明确的划界:
- **BPM 审批放量后启用**。上级设计已定:放量前创作页置灰、配置改动者是创始人本人、属非关键即时改。所以阶段二把审核落成状态机里的一个挂点(见 §3.2),放量前创始人角色从"草稿"直接到"激活"、审批自动通过;放量后打开 `huijing-module-bpm` 审批流,同一状态机不改。**不在本阶段验证真实审批流**。
- **配置编辑 UI 属阶段三**。阶段二只交付后端治理层、版本化、激活编排与 NacosHotConfig 接线;编辑表单由阶段三在 game-admin 落地,消费 AgentScope 的 `/agent/schema`
- **观测属阶段四**(Studio + genMonitor)。
- **机制级激活原子性留放量后**。一个配置集的多次 PATCH/publish 机制上非原子,MVP 取静默期语义规避(单操作者 + 创作页置灰,blast radius 小);真机制级原子(epoch 戳)留放量后。这条沿用上级 §3.3,不在本阶段重推。
## 3 方案
### 3.1 配置中心的两半:yudao 治理与版本账本 ⊕ Nacos 生效下发
配置中心把职责劈成两半,各用现货、不自建下发机制。**yudao 管治理与版本账本**:编辑的鉴权、`creator` 归因、放量后的 BPM 审批、激活状态机、操作审计,连同每次定版落下的版本行——权限、审计、CRUD 全是 yudao 作为成熟后台框架的原生件,game-cloud 是它的 fork,直接复用。**Nacos 管生效下发**:长轮询推送、客户端磁盘快照兜底、命名空间隔离——这些是 Nacos 成熟的下发通道,阶段〇已自托管进 mini-infra,预算/门阈值那一路的热推全靠它(路 B,见 §3.3)。
版本账本落 MySQL 而不落 Nacos,基于三个约束确定,第一个就是创始人拍 B 时点名要解的:
- **prompt 正文放不进 Nacos**。Nacos 单配置内容默认上限 100KB(容量保护 `defaultMaxSize`)。prompt 的实际规模有两个量级:Python 角色源文件(`cheap_roles.py` 30499B、tier2 `roles.py` 24539B,含多角色内置 prompt 与配套代码,非单条运行时 prompt)与外置 prompt 文件(`contracts/prompts/04-config/cheap-system.md` 14695B 为当前最大单条、tier2 最大单条 `writer-system.md` 4970B)。单条运行时 prompt 现在离 100KB 尚有余量,但配置集版本要把一档的 system_prompt 连同 few-shot、多角色配置一起收进一行,内容会随 few-shot 与角色规模增长向上限爬。把最大、改得最勤的旋钮放在接近 Nacos 单配置上限的位置,不如一开始就换地方。
- **定版要原子**。版本行(元数据 + 全量内容)同库同事务一次落;内容若在库外,定版就成了跨系统写,要补超时/重试/补偿——治理层最高频的动作不该是分布式事务。而 prompt 一旦出 Nacos,版本若劈成"prompt 在 MySQL、小参在 Nacos"两处,一次定版跨两系统、必漂移,所以账本整体落 MySQL。
- **diff 与检索要就地**。版本 diff、按内容查历史都是版本行上的本地操作;内容在外部系统则每次 diff 都要来回取对象。
**prompt 内容列定 MySQL `MEDIUMTEXT`,不选 MinIO**——在此确定、不留开放项。MinIO 在本项目的设计定位是成品源工程归档的后端 seam(`store.py` 的 BackendStore 声明 MySQL manifest + MinIO 源文件、内容哈希、id+version 寻址,目前是接口占位,真正在用的是 LocalFsStore 本地文件实现),那是"多文件源树"的形状;prompt 是"一段文本字段"的形状,几 KB 到几十 KB,MinIO 的价值(大对象、二进制、流式)一样都用不上,却把定版原子性与就地 diff 全破掉,还把备份从"一份 MySQL dump = 治理+内容一致快照"劈成两个系统。列型取 `MEDIUMTEXT`(16MB)而非 `TEXT`(64KB):30KB 级 prompt 加 few-shot 有越过 64KB 的现实可能,MEDIUMTEXT 给足余量且无额外成本。版本表的实现约束一并明确:表用 `InnoDB + DEFAULT CHARSET=utf8mb4`;prompt 正文列不建全文或普通索引(只做整行读写、不参与检索),另存 `content_hash``content_bytes` 两列供快速比对与容量核对(`content_bytes` 按 utf8mb4 字节数计,防混淆字符数与字节数);备份恢复以包含版本行正文的 MySQL dump / binlog 为口径,而非只抽结构不抽内容;两版 diff 在应用层做。
对上级设计"自建版本表 = 重造 Nacos"的判定要诚实交代:那条针对的是**版本化下发机制**(推送/快照/回滚/灰度),这部分仍然全买——路 B 热推是 Nacos、基建配置通路是 Nacos SCA;挪回 MySQL 的只是**版本行**这张普通 yudao 业务表,借的全是 yudao CRUD/分页/审计原生能力,没有一行自建下发机制。此口径回调上级 §3.3 等处,挂账见 §7。
于是四方各就各位:
- **yudao(game-cloud)**:配置集元数据 + 版本行(全量内容含 prompt,`MEDIUMTEXT`)+ 当前激活版指针 + creator + 状态机 + 审批挂点 + 操作审计 + 激活编排。治理与账本权威。
- **Nacos**:路 B 生效下发通道——激活时 publish 预算/门阈值到生效 dataId,worker 长轮询热读;**不再承版本账本**(生效 dataId 上的配置历史只是运维排障的顺带留痕,不是权威)。
- **AgentScope Service 的 Redis**:路 A(prompt/模型/参数)生效投影(激活时 PATCH 写入,每 POST 现装配读出;Service 只认自己的 Redis、不认 Nacos,所以路 A 生效只能靠 PATCH)。
- **worker 进程内 genconfig**:路 B 生效投影(经 NacosHotConfig 从 Nacos 热读)。
账本单点(MySQL 版本行)、投影两处(Redis / Nacos 生效 dataId)、消费两路(Service per-POST / middleware 构造)——权威与投影的关系清晰,§3.6 的漂移对账就建在这上面。
### 3.2 配置对象与生命周期:改 → 版本 → 审核 → 激活 → 回滚
治理的单元是**配置集**,不是单个旋钮。一款档位的生成行为由一组协同旋钮共同决定——便宜档配置集 = 便宜档 agent 的 system_prompt + M3 模型 + 参数(max_tokens/thinking)+ 软预算目标 + 门阈值;tier2 富游戏配置集 = tier2 agent 的 prompt + glm-5.2 + 参数 + 预算 + 门阈值。以配置集为激活单元,才能让一组本该一起变的旋钮一次激活、不出现"新 prompt 配旧模型"的半拉子状态。
一个配置集走这样一条生命周期:
```mermaid
stateDiagram-v2
[*] --> 草稿: 创始人在 yudao 编辑一组旋钮
草稿 --> 待审: 定版(版本行落库,creator/时间随行)
待审 --> 已激活: 审核通过(MVP 创始人角色直接激活 · 放量后走 BPM 审批)
已激活 --> 待审: 编辑出新版本
已激活 --> 已激活: 回滚(取历史版本行,重放激活)
已激活 --> 已归档: 被更新版本取代
待审 --> 草稿: 驳回
```
![图 3 · 激活一致性状态机](assets/cfgctl2-03-激活一致性状态机.svg)
几个关键点。**激活之前 Nacos 完全不被触碰**:草稿与版本行都是 yudao 库内数据,配置内容到"激活"才第一次离开治理库——这天然堵死了"草稿提前生效"的口子(Nacos 的配置是 publish 即被监听者读到的,预算/阈值若提前进 Nacos 就绕过了激活闸)。**激活是独立的闸**:它把选定版本的内容双路下发(见 §3.3),并把"当前激活版指针"指过去。**回滚就是重放激活**:取历史版本行的内容,走一遍激活动作,幂等。**归因与审计随生命周期自然沉淀**:定版记 creator 与时间,激活/回滚是一条 yudao 操作日志,diff 是两条版本行的就地比对——全是 yudao 原生能力,不新造。
### 3.3 双路激活:PATCH 路 ⊕ Nacos 热读路
![图 2 · 双路激活编排](assets/cfgctl2-02-双路激活编排.svg)
激活一个配置集,编排层从选定的版本行取内容,按旋钮性质分两路下发:
```mermaid
flowchart LR
ACT["yudao 激活编排<br/>(取选定版内容)"]
ACT -- "路A:prompt/context/max_iters" --> PA["PATCH /agent"]
ACT -- "路A:模型/参数/thinking/temp" --> PS["PATCH /sessions"]
PA & PS --> REDIS[("AgentScope Redis<br/>当前配置")]
REDIS -- "每 POST 现装配(热)" --> GEN["/chat 生成回合"]
ACT -- "路B:软预算目标/门阈值" --> PUB["publish Nacos 生效 dataId"]
PUB --> HC["worker NacosHotConfig<br/>长轮询推送热读"]
HC --> GENC["genconfig 门面"]
GENC -- "middleware 构造时读" --> GEN
ACT -- "记当前激活版 + 操作日志" --> YU[("yudao 治理表")]
```
- **路 A(prompt/模型/参数)**:激活编排把内容 PATCH 进 AgentScope Service 的 `/agent`(system_prompt / 压缩比例 / tool_result 截断 / max_iters)与 `/sessions`(模型 / 协议 type / credential / max_tokens / thinking / reasoning_effort / temperature)。`/sessions` 的 PATCH 在顶层是部分字段更新语义(`exclude_unset`,只改本次带上的顶层字段),但模型与参数都封在 `chat_model_config` 这一个子对象里,而该子对象一旦出现即被**整体替换**——顶层 `exclude_unset` 不深合并它内部的 `parameters`,且 `type`/`model` 是必填字段。所以激活编排改任一模型参数(哪怕只动 max_tokens 或 thinking)都必须从版本行组装出完整的 `chat_model_config`,把 `type`/`credential_id`/`model`/`parameters` 全带齐,不能只发局部对象,否则未带上的字段会被清空。写进 Service 的 Redis 后,下一个 POST `/chat` 现装配即生效。
- **路 B(软预算目标 / 门阈值)**:这些参数不在 `/agent`+`/sessions` 里,它们是 worker 的 middleware 在构造时从 genconfig 读的。激活编排把内容 publish 进 worker 监听的 Nacos 生效 dataId,NacosHotConfig 经长轮询推送热读进进程内,genconfig 从它取到新值,下一次 middleware 构造时读到。这里有一处 dataId 粒度要定死:cheap-worker 与 tier2 gen-worker 是两个独立进程、各接一个 NacosHotConfig,两档 key 命名本就不同(cheap 用 `cheap_rmb_hard_limit`、tier2 用 `rmb_hard_limit`)。**路 B 生效 dataId 按档隔离**——cheap 与 tier2 各用一个专属 dataId,而不是共用一个 `gen-hot-params` 整体替换;否则激活一档的配置集会把另一档的 key 从该 dataId 上冲掉(publish 是整内容替换,worker 初读/重启即缺 key)。激活哪一档,就只 publish 那一档的 dataId。
**为什么静默期语义在这个模型下几乎是自然的**:两路生效都发生在"下一次生成"的边界上——路 A 的 Redis 在 `/chat` 进 session 锁之前读、路 B 的 genconfig 在 middleware 构造时读,正在跑的那一局早已经读过配置了,新配置只影响此后新起的 POST。所以并发引起的撕裂窗口只剩一个:一个配置集的多次 PATCH/publish 之间非原子,理论上并发一局能读到"路 A 新、路 B 旧"的组合。MVP 单操作者 + 创作页置灰把这个并发窗口的影响面压到零,取静默期语义即可;真机制级原子留放量后(上级 §3.3)。
还有一个撕裂窗口不是并发引起、静默期也兜不住,要如实交代:**激活自身中途失败**。双路投影是"写即被读"——PATCH 写进 Redis 即被下一 POST 装配,publish 进 Nacos 即被 worker 长轮询推送读到,两路之间没有分布式事务。若激活先成功下发一路、再在另一路失败,已发出的那一路在投影层已经生效、不会自动回退;此刻"当前激活版指针不前移"只保住**账本**语义(见 §3.6),保不住投影。所以本设计不写"绝不留半生效态"这种投影层做不到的强承诺,而是要求激活编排在任一路失败时**立即补偿**:把已成功下发的那一路重推回上一激活版的内容(配置中心持有上一版,可做),不等定期对账。激活编排对此的硬要求是:一批下发须**幂等**、**任一步失败即整批判未生效、立即把已成功路补偿重推回上一激活版、再标为可重试**(见 §3.6 失败模式)。
### 3.4 NacosHotConfig 接进 genconfig(阶段〇 follow-up 落地)
预算/门阈值那一路的热读,是把 `nacos_hotconfig.py` 接进既有的 genconfig 门面,而不是改 middleware。现状链条是 `middleware → genconfig.get("budget", "rmb_hard_limit")`,genconfig 现有取值优先级是 **env 覆盖 > 外部 `generation.yaml` > 内置默认 > 调用方 default**;它已经是一个带缓存、带 best-effort 兜底、带内置默认、支持 env 单点覆盖的进程内配置门面,middleware 到处在调它。阶段二只换 genconfig 的**读取后端**:把 NacosHotConfig(配置中心激活投影)接成新的热源。
接入后 Nacos 热源与 env 的相对优先级必须定死、不能留空:**Nacos 热源 > env > 外部 YAML > 内置默认 > 调用方 default**。理由是配置中心才是权威,机器上遗留的实验 env 不应静默压过激活值——否则会出现"配置中心已激活、机器上却不生效"的难查故障(操作者在配置中心看不到机器上的 env)。env 由现状的最高优先级降为"Nacos 取不到时"的回落层之一,保留其一次性实验逃生舱的作用;同时把 env 覆盖纳入 §3.6 漂移对账口径:对账发现某旋钮实际生效值来自 env 而非当前激活版时,一并告警。
这样接线有三处好处。其一,**middleware 一行不改**:`genconfig.get(...)` 的调用面完全不动,CircuitBreakerMiddleware 的软预算目标、门判的阈值都自动吃上 Nacos 热读。其二,**回落链天然是 fail-safe**:Nacos 不可达时 NacosHotConfig 自带本地磁盘快照兜底,再不行 genconfig 回落 env、本地 YAML 与内置默认,生成主链不被配置中心连累。此外 NacosHotConfig 侧要补一道值 fail-safe:它现在只挡空/脏 JSON、不校验业务范围,一个合法 JSON 但语义非法的值(负预算、超小超时)会直接 update 进热参;要改成遇语义非法值时**保留旧值 + 告警、不覆盖当前热参**,把错值挡在生成链之外(激活前的正向值域校验见 §3.6)。其三,**尊重既有 working code**:genconfig 是雏形阶段就在的进程内配置层(SoT §5.2 提到的那个雏形),阶段二是把它的源从本地文件提升到集中版本化,不是推翻重造。
命名空间上有一个已知的坑必须先解:**Nacos 默认公共空间的 namespaceId 是空串,不是字面量 "public"**(阶段〇 follow-up 明确)。业务生成配置的 dataId 要么显式放进一个专门的命名空间(用真实 namespaceId、不是 "public" 三个字母),要么明确用空串走默认空间;写侧(yudao publish)与读侧(worker NacosHotConfig 订阅、game-cloud SCA)必须对齐同一个真实 namespaceId,否则激活写进一个空间、worker 在另一个空间读、配置永远推不到。
这不止是一句提醒,而是一项**阶段二必修前置任务**:现状代码里 namespace 口径已经与"空串"这一事实不一致——Java `game-cloud/huijing-server/.../application.yaml` 两处写 `namespace: public`、Python `tier2/gen-worker/service/nacos_registry.py` 默认 `os.environ.get("NACOS_NAMESPACE", "public")``test_nacos_registry.py` 还断言 `"public"`。若阶段二写侧按空串、读侧沿用 `public`,路 B 会静默推不到。所以在接线动作之前先统一口径:走默认公共空间就把该配置项置空/删除、而不是填字面量 `"public"`,并同步改 Java 配置、Python 默认值、对应测试断言与凭据档(`docs/内网凭据与端点.md`)。这一步排在步骤 4 接线之前(见 §4)。
### 3.5 分工边界:基建配置 vs 业务生成配置
配置控制面用了 Nacos,阶段〇的基建也用了 Nacos,两者必须划清,否则治理层会误伸手去管运维配置、或运维改配置时绕过了该有的审计。判据是一句话:**谁改、改了要不要治理**。
| | 基建配置 | 业务生成配置 |
|---|---|---|
| 例子 | game-cloud Spring 配置、Sentinel 流控规则、RocketMQ 参数、服务发现 | prompt / 模型 / 参数 / 软预算 / 门阈值 |
| 谁改 | 运维 / 开发 | 创始人 / 运营 |
| 要不要治理 | 不要——即时热生效即可 | 要——版本 / 审计 / 审批 / 可回滚 |
| 通路 | Nacos SCA 原生(`spring-cloud-starter-alibaba-nacos-config`,dataId 按应用名,@RefreshScope 或重启) | yudao 治理层(MySQL 版本行为账本)→ 激活时 PATCH Service + publish 生效 dataId |
| 消费方 | game-cloud 各 Java 服务 | AgentScope Service(PATCH)+ Python worker(NacosHotConfig) |
两者共用 Nacos 这套下发基础设施,但治理路径分开、命名空间或分组隔离。基建配置那条阶段〇已经接好、跑在生产,阶段二不碰它;阶段二只在 Nacos 上开一块属于业务生成配置的地(路 B 生效 dataId),由 yudao 激活编排独占写入。
### 3.6 失败模式与兜底
![图 4 · 漂移对账三态](assets/cfgctl2-04-漂移对账三态.svg)
激活是一批跨系统的非原子写(PATCH Service + publish Nacos + 更新 yudao 指针),这里的失败模式要正面处理,不能让配置中心把生成链路带崩。
- **激活失败即时补偿(账本语义,不作投影强承诺)**。一批下发里任一步失败(某个 PATCH 返错、Nacos publish 超时),整批判**未激活**:yudao 当前激活版指针**不前移**,保留上一激活版为账本权威。但双路投影是"写即被读"、两路间无事务,已成功下发的那一路在投影层已经生效——指针不前移只保住账本、保不住投影。所以失败处置不能停在"判未激活",必须**立即补偿**:把本批已成功下发的那一路(PATCH 或 publish)重推回上一激活版的内容,再标为可重试。补偿与重放都要幂等(同一版本重推无副作用)。这样账本与投影一起收敛回上一激活版,不留"路 A 新、路 B 旧"的持续撕裂;而不是把"绝不留半生效态"写成投影层做不到的强承诺、再靠定期对账慢慢兜。
- **MySQL 不可达 / 指针写失败**。激活还含"读版本行、写激活尝试、前移当前激活版指针、记审计"这几步 yudao 库内写,两种情形分开处置:(a) 起步读版本行时 MySQL 不可达——直接拒绝激活、不发起任何下发,生成继续用旧投影。(b) 三路投影(PATCH `/agent`、PATCH `/sessions`、publish Nacos)都成功、最后前移指针或写审计时 MySQL 失败——此刻投影已是新版、账本仍指旧版,是确定漂移。处置:激活状态先持久化为 `ACTIVATING`(下发前落、全部成功后才转 `ACTIVE`),恢复任务按激活尝试幂等地二选一执行到底——要么补提交指针(投影既已是新版,对齐账本),要么补偿重推旧版回投影并回滚该尝试,不停在中间态。
- **配置值本身非法(合法但语义错)**。激活链是"改 → 定版 → 激活",对预算写错单位(元/分混)、预算填成天文数、超时给到过小、`max_tokens ≤ thinking_budget`、模型协议 type 与 credential type 不匹配这类**类型正确但语义错**的值,若无校验会一路激活、下一局生效——预算是成本红线旋钮,配错直接让软预算失效、成本超支。所以激活前加一道**值域 sanity 校验**:预算为正数且落在合理区间、单位固定;超时有下限;`max_tokens > thinking_budget`;模型协议 type 与 credential type 匹配;prompt 非空。校验不过直接拒绝激活。NacosHotConfig 读侧再兜一道(§3.4:语义非法值保旧值 + 告警);仍漏过的错值挂阶段四观测(成本异常告警)事后发现。
- **Service 不可达**。路 A 依赖 Service 在线才能 PATCH。Service 不可达时激活判失败,按上面的补偿口径处置(路 A 尚未成功、无需补偿路 A;若路 B 已 publish 成功则补偿重推路 B 回旧版),保留上一激活版;Service 上跑的还是它 Redis 里的旧配置,生成不中断,只是新配置没生效。Service 恢复后重放激活即可。
- **配置漂移检测**。Service 的 Redis 投影可能与"当前激活版"漂移——Service 重启若 Redis 未持久化会丢配置回落缺省、或有人绕过治理直接改了 Redis/Nacos、或某次激活部分失败没补偿干净、或机器上遗留 env 压过了本该生效的激活值。配置中心提供一个对账:激活后与定期,拉 Service 的 `/agent`(AgentScope 无单个 GET `/agent/{id}`,用列表端点按 id 过滤)+`/sessions` 当前配置比对当前激活版的路 A 内容;拉 worker 的生效投影比对路 B 内容(含 env 覆盖口径:实际生效值来自 env 而非激活版时也算漂移;Nacos publish→read 最终一致,读带 8s 容忍窗、避开刚激活的收敛中间态);对不上即告警,并支持一键重推(重放激活把投影拉回激活版)。这道对账是"配置中心为权威、Service 与 worker 为投影"这个定位的兜底闸,但不是失败的第一道防线——第一道是上面的即时补偿。
- **命名空间错配**。见 §3.4:写读两侧的 namespaceId 必须是同一个真实值,默认空间是空串非 "public",且现状代码的 `public` 字面量偏差要作前置任务先修。这条在接线时一次性核对确认,避免配置静默推不到。
## 4 步骤计划
(阶段序 SVG 待补)
阶段二自身按依赖分五步串行,另有一项 namespace 口径统一作为接线前置;阶段三(UI)、阶段四(观测)作为后续阶段划界在后,各自后续出 plan。
```mermaid
flowchart LR
S1[步骤1<br/>配置集建模<br/>+ yudao 治理骨架] --> S2[步骤2<br/>版本行与历史 MySQL<br/>回滚/diff]
S2 --> S3[步骤3<br/>双路激活编排]
S1 --> S4[步骤4<br/>NacosHotConfig<br/>接进 genconfig]
S3 --> S5[步骤5<br/>失败兜底<br/>+ 漂移对账]
S4 --> S5
S5 --> N3[阶段三 UI<br/>后续出 plan]
N3 --> N4[阶段四 观测<br/>后续出 plan]
```
**前置 · namespace 口径统一**(排在步骤 4 接线之前)
- 交付:把现状代码里的 `namespace: public` 字面量偏差统一成同一个真实 namespaceId(走默认公共空间就置空、而非填 "public"),覆盖 Java `application.yaml`(两处)、Python `nacos_registry.py` 默认值、`test_nacos_registry.py` 断言与凭据档 `docs/内网凭据与端点.md`(见 §3.4)。
- 验证:写侧(yudao publish)与读侧(worker NacosHotConfig、game-cloud SCA)落在同一真实 namespaceId;既有服务发现/注册不回归。
- 风险:不先修这项,路 B 写读会静默错空间、步骤 4 接线无从验证。
- 落地(`b2b4d389`):namespace 口径统一,Java/Python/测试/凭据档已对齐同一真实值。
**步骤 1 · 配置集建模 + yudao 治理骨架**
- 交付:在 game-module-aigc 落一个生成配置治理子域(复用 yudao 的鉴权/creator/审计框架,不塞进 infra_config 的 KV 表——生成配置是结构化配置集、不是键值对)。定义配置集的数据模型(一个配置集含哪些旋钮、映射到哪些 `/agent`+`/sessions` 字段与哪些 Nacos 生效 key)、版本与当前激活版指针、生命周期状态机、creator 与操作审计。
- 验证:能建/改/定版一个配置集,creator 与时间随版本落库;权限门挡住无权写;状态机流转符合 §3.2。
- 依赖:yudao(game-cloud 已在)。
- 风险:配置集与 AgentScope agent/session 的字段映射要对齐 `/agent`+`/sessions` 的真实 schema(消费 `/agent/schema`),映射错则激活 PATCH 无效。
- 落地(`3ae34de1`):配置集建模 + yudao 治理骨架 + 版本行(步骤 1、2 同提交,MySQL 治理子域 Flyway V29/V30)。
**步骤 2 · 版本行与历史(MySQL)**
- 交付:定版落版本行——配置集全量内容(prompt 存 `MEDIUMTEXT` + 模型/参数/预算/阈值)与元数据同库同事务一次写成一行;历史列表、任一历史版取回、两版 diff;当前激活版指针只由激活动作前移(定版不动它)。
- 验证:定多版后能列历史、取任一版、diff 两版;定版是单库事务、无跨系统写;30KB 级 prompt 正文完整存取无截断,并加一个 **64KB 边界样本**(越过 `TEXT` 上限、验证 `MEDIUMTEXT` 存取无截断)与 **utf8mb4 字节数校验**(`content_bytes` 按字节而非字符计,含多字节中文/emoji 时口径正确)。
- 依赖:步骤 1。
- 风险:版本行只增不删,量级 = 人工定版频次(每天几次),多年不清理也只是几千行——留一个归档策略位即可,不做提前优化。
- 落地(`3ae34de1`):版本行与历史/回滚/diff(步骤 1、2 同提交)。
**步骤 3 · 双路激活编排**
- 交付:激活动作先做值域 sanity 校验(§3.6),通过后把选定版双路下发——路 A PATCH `/agent`+`/sessions`(模型/参数从版本行组装完整 `chat_model_config`,§3.3),路 B publish 进 worker 监听的按档隔离生效 dataId;更新当前激活版指针 + 记操作日志;成组下发幂等、任一步失败即整批判未生效并立即补偿重推已成功路回上一激活版、再判可重试(见 §3.6);静默期语义(只对下一批新生成生效)。
- 验证:改任一旋钮 → 定版 → 激活 → 下一次生成生效;并发两局不读到路 A 新/路 B 旧的撕裂组合(静默期);回滚旧版即恢复;一批下发中途失败时指针不前移、已成功路被补偿重推回旧版、可重试;非法值(负预算等)在激活前被拒。
- 依赖:步骤 1、2;阶段一②(两档已归并 Service,PATCH 有落点)。
- 风险:激活一致性是本阶段最重的风险(§3.6);Service PATCH 与 Nacos publish 跨系统,须幂等 + 判未生效可重试。
- 落地(`72973532`):双路激活编排;路 A `/sessions` 复数端点修复 `22444fd5`(早稿单数 `/session` 与真实路由不符)。
**步骤 4 · NacosHotConfig 接进 genconfig**(依赖上方 namespace 口径统一前置)
- 交付:genconfig 的读取后端提升到 Nacos,落地阶段〇 D2 建好未接线的 `nacos_hotconfig.py`,拆两件。(1) 新增 worker 启动期的 **HotConfig 单例工厂**:`nacos_hotconfig.py` 明确只消费已建好的 v1 `NacosClient`、不自建 client,所以工厂负责把 client 构造齐——server 地址、鉴权(账号密码)、`NO_PROXY`(内网直连绕系统代理,阶段〇同款坑)、真实 `namespaceId``group`、按档隔离的 `dataId`,再注入进 NacosHotConfig 并接进 genconfig。(2) genconfig.get 的取值链前端接热源:优先查 NacosHotConfig,再依次回落 env、本地 `generation.yaml`、内置默认(优先级见 §3.4)。middleware 调用面一行不改。
- 验证:改 Nacos 生效 dataId → worker 数秒内经 genconfig 读到新预算/阈值(不重启);单测覆盖四条异常/回落路径——**未 start**(工厂没起 NacosHotConfig → genconfig 回落 env/YAML/默认)、**Nacos 不可达**(NacosHotConfig 磁盘快照兜底,再回落本地)、**namespace 配错**(写读不同空间时读不到,佐证前置任务的必要)、**YAML 回落**(热源无值时取本地 YAML 与默认);cheap 与 tier2 两档各读各的 dataId、软预算目标与门阈值都吃上热读。
- 依赖:阶段〇 Nacos + NacosHotConfig(已建);阶段一①(middleware 经 genconfig 读预算/阈值);namespace 口径统一前置。
- 风险:genconfig 现有缓存与 NacosHotConfig 的推送时序要理顺(别让本地 YAML 缓存盖住 Nacos 热值);回落链优先级(Nacos > env > YAML > 默认)要测到位。
- 落地(`344330a4`):NacosHotConfig 接进 genconfig 作热源;worker 启动期 HotConfig 单例工厂入口装配 `d9def7d9`
**步骤 5 · 失败兜底 + 漂移对账**
- 交付:激活失败整批判未生效 + 保留上一激活版 + 可重试;Service 不可达兜底;配置漂移对账(拉 Service/worker 投影比对当前激活版)+ 一键重推。
- 验证:模拟 PATCH 中途失败/Service 不可达 → 指针不前移、生成用旧配置不中断、重放激活恢复;篡改 Redis/生效 dataId 后对账能检出漂移并重推拉回。
- 依赖:步骤 3、4。
- 风险:漂移对账要区分"真漂移"与"正在激活的中间态",避免误报。
- 落地(`a8dd5e50`):失败兜底 + 漂移对账(对账读带 8s 容忍窗避开激活收敛中间态)。
**后续阶段(划界,各自出 plan)**:阶段三 = game-admin 配置编辑面(浏览/改/定版/激活/回滚/历史/diff,表单消费 `/agent/schema`),依赖阶段二;阶段四 = 观测(Studio + genMonitor,trace 回放/成本对账/在跑监控),依赖 trace 事件流。两者不在本设计展开。
## 5 验证方式
1. **配置即数据、版本可管**:改 model/budget/max_tokens/thinking/prompt 任一 → 定版 → 激活 → 下一次生成生效;回滚即恢复;逐项覆盖本会话手改过的硬编码点。
2. **归因与审计**:每次定版记 creator/时间,激活/回滚有 yudao 操作日志,任意两版可 diff。
3. **双路激活、静默期无撕裂**:路 A PATCH、路 B Nacos 热读都生效;一组旋钮作一个配置集激活;并发两局不读到跨路撕裂组合。
4. **NacosHotConfig 接线**:改 Nacos 生效 dataId,cheap 与 tier2 的软预算/门阈值经 genconfig 数秒内热读到新值、不重启;Nacos 不可达回落本地 YAML 与默认、生成不受影响。
5. **分工边界**:基建配置仍走 SCA 原生通路、不经治理层;业务生成配置的写入只由 yudao 治理层独占。
6. **失败兜底**:激活中途失败/Service 不可达时指针不前移、生成用旧配置不中断、重放可恢复;漂移可检出并重推。
## 6 风险与回滚
- **激活一致性(本阶段最重)**:一批 PATCH+publish 跨系统非原子、投影写即被读。缓解 = 值域 sanity 校验前置 + 幂等 + 任一步失败即整批判未生效并立即补偿重推已成功路回上一激活版 + 当前激活版指针只在整批成功后前移 + 保留上一激活版为账本权威(投影层撕裂由即时补偿收敛,不靠"绝不半生效"这种投影层做不到的强承诺);并发撕裂 MVP 由静默期规避,机制级原子(epoch 戳)留放量后。MySQL 指针写失败而投影已成功时,以 `ACTIVATING` 持久态 + 幂等恢复对齐(§3.6)。回滚 = 配置中心永远能重放上一激活版。
- **Service 不可达 / Redis 未持久化丢配置**:激活判失败保留旧版;Service 恢复后由漂移对账检出并一键重推。Service Redis 的持久化策略需与运维确认(丢配置是否需 Service 启动即从配置中心拉激活版自愈,可作后续增强)。
- **NacosHotConfig 接线破坏 middleware 读参**:回落链(Nacos → env → 本地 YAML → 内置默认,优先级见 §3.4)是保命绳,先在两档单测里锁死整条回落链再上;真接线灰度——先只把一个低风险旋钮(如门阈值)切到 Nacos 热读、验稳再推预算目标。回退 = genconfig 后端切回纯本地 YAML(改一处开关)。
- **命名空间错配**:默认空间是空串非 "public";现状代码的 `public` 字面量偏差作前置任务先修(§3.4 / §4 前置),写读两侧 namespaceId 一次性核对对齐,否则配置静默推不到(阶段〇同款坑)。
- **配置集字段映射漂移**:配置集到 `/agent`+`/sessions` 字段的映射依赖 AgentScope schema,框架升版可能变;映射以 `/agent/schema` 为准、加一致性校验,别硬编码字段名。
- **SoT 收口**:本阶段落地后,须把 SoT 里 GitOps/Langfuse 式的旧口径收敛为 yudao 配置中心版本化(账本落 MySQL 版本行)——§5.2 管理面配置管理、§5.8 配置三类的"受治理发版"、ADR-4 配置热取、A13 配置注册表四处,与上级设计 §6 pending 是同一收口面,收口时一并回写,避免两份自称权威触 canonical 门;对上级设计本身的口径回调逐条挂账在 §7,由编排层另单收口、本档不动上级档。
## 7 收口涟漪清单(挂账,由编排层另单收口)
版本账本从 Nacos 挪进 yudao MySQL 版本行(§3.1)回调了上级设计已评审的几处口径。按创始人指令,本档**不改上级档**,在此逐条挂账;收口时随上级 §6 已挂的 SoT 收口单一并执行、不双开。
| # | 位置 | 现口径 | 应回调为 |
|---|---|---|---|
| 1 | 上级设计 §0 / §3.3 / §3.7"互补"行 | "Nacos 管版本化存储与下发(版本历史/回滚/diff/灰度/推送),取代自建 Flyway 版本表 + 薄读接口" | 版本账本落 yudao MySQL 版本行(prompt 100KB 上限 + 定版原子性所迫,§3.1);Nacos 收窄为路 B 生效下发;"消灭薄读接口"结论不变(NacosHotConfig 仍替它);"灰度发布"收窄为路 B 生效 dataId 层能力、MVP 不启用 |
| 2 | 上级设计 §4 阶段二节(交付/验证/风险) | "激活时把 active 版写进 Nacos 并 PATCH""Nacos 承版本/回滚/灰度/推送(取代自建 Flyway 版本表 + 薄读接口)" | 交付 = yudao 治理子域(版本行 + 状态机 + 激活编排)+ 双路激活 + NacosHotConfig 接 genconfig;验证/风险按本档 §4/§6 |
| 3 | 上级设计 §3.6 mermaid(UI→yudao→NACOS 写版本→激活 PATCH) | 版本写进 Nacos、激活自 Nacos 侧发出 | yudao(MySQL 账本)→ 激活编排双路下发(PATCH `/agent`+`/sessions` · publish 生效 dataId);图随文改 |
| 4 | 上级设计 §3.3(middleware 用 nacos-sdk-python `add_listener` 订阅)/ §3.7 生产图(Python middleware 直读预算/阈值)/ §4 阶段〇(middleware 接 nacos-sdk-python listener 读预算/阈值) | middleware 经 nacos-sdk-python `add_listener` 直读 Nacos | middleware 经既有 genconfig 门面读、NacosHotConfig(v1 `add_config_watcher` 长轮询推送)作 genconfig 热源(§3.4);middleware 调用面不变,底层由"直读 Nacos"改为"genconfig 门面 + 热源"。上级核心结论(middleware 从 Nacos 热读预算/阈值、fail-safe 靠 SDK 快照兜底)不变,回调的是实现路径口径;此偏差实由阶段〇引入、阶段二继承 |
| 5 | SoT 回写口径(架构图说 §5.2 / §5.8 / ADR-4 / A13;上级 §6 已挂"GitOps 口径"收口项) | GitOps / Langfuse 式热取叙述 | "配置中心版本化"的落点 = yudao MySQL 版本行 + 双路激活(本档 frontmatter sot-impact 申报);与上级挂的收口单合并执行 |
另挂一条**知识面治理归属(2026-07-04 知识面审计 → 创始人 2026-07-04 已裁「进配置集」)**:知识件——品类评分尺 fixture(`cheap-worker/fixtures/genre-rubrics/`)、品类设计 skill、few-shot 金标——此前既不在本档「配置集」范围内、也不在其它治理面上(变更无版本定版、无审计回滚,fixture↔skill 内联副本双写只靠 rubric-sync-gate 人肉对账)。**创始人 2026-07-04 决策6 裁定:纳入配置集受版本治理**。这是本阶段的一个范围增量,须另出设计/plan 落地——关键设计点:① 三类知识件的配置对象建模(rubric fixture=结构化 JSON、skill=markdown、few-shot 金标=样本集),映射进配置集版本行;② 配置中心成为单一真源后,`cheap-worker/fixtures/` 与 skill 内联副本降为投影,现行 rubric-sync-gate 双写对账门相应改造为「配置中心→投影」的单向下发校验;③ 生效通路(知识件不走 `/agent` PATCH、也非预算/门阈值那类小参 Nacos 下发,而是随 worker 读取的 fixture/skill 文件——生效形态需另定,可能经版本行导出到 worker 可读路径或 RAG 索引)。裁前落地按现范围(知识件不入),此增量排在阶段二五步之后、与阶段三 UI 同批或紧随。
## 8 实施工单(六要素 · 2026-07-04 排期,opus 自治领单)
**目标**:按 §4 交付「namespace 口径统一」前置 + 步骤 15,把生成配置升级为「yudao 定版 → 双路激活 → 数秒热生效」的受治理配置中心;完成即逐条兑现 §5 六条验证。阶段三 UI、阶段四观测不在本单。
**事实指针**:设计 = 本档(方向 B 已拍、双评审 11 条全修);上级 = 2026-06-30 总设计(阶段〇/一①/一② 已落地)。代码基线全在 frontmatter 关联段:`genconfig.py`(env→YAML→内置三级 + mtime 缓存)、`nacos_hotconfig.py`(阶段〇已建未接线)、`middleware.py:173`(软预算经 genconfig 读)、`cheap_service_app.py` / `service/app.py`(PATCH 落点)、game-module-aigc(治理子域落点)。部署面:Nacos 在 mini-infra(ssh 真 IP `100.64.0.8`),worker/Service 在 mini-desktop(`100.64.0.7`);凭据一律读 `docs/内网凭据与端点.md`,不问、不设 env。近期阈值批(writer 60 / step 100 / 墙钟 2700,`bfeaea2d`)已在 `generation.yaml`,接线以现值为准。
**边界红线**:基建配置通路(SCA 原生)不动(§3.5);middleware 调用面一行不改(只换 genconfig 底层热源);不改上级设计档(涟漪已按 §7 挂账);知识件(品类 rubric fixture / skill / 金标)在 §7 末创始人裁定前不入配置集、按现范围实施;live 变更逐次报(决策包⑥ 授权边界)。
**验收门**:§5 六条逐条真验 + §4 各步骤「验证」全绿;Python 单测绿——回落链四条异常路径(未 start / Nacos 不可达 / namespace 错配 / YAML 回落)先在单测锁死才许真接线;Java 单测 + Flyway replay 绿;灰度顺序 = 先门阈值、验稳再切预算目标;docs-gate 绿。
**坑(前车之鉴,本仓全部真栽过)**:① Nacos 默认空间 namespaceId = 空串而非 `"public"`,前置任务不先修则写读静默错空间;② 内网直连必须绕系统代理(`NO_PROXY` / `ProxyHandler({})`,阶段〇 worker 回调 502 同款);③ genconfig 的 mtime 缓存别盖住热值,回落优先级(Nacos > env > YAML > 内置)要测到位;④ 新旋钮禁止在调用点写死默认值——双源默认值影蔽刚在收敛环栽过(DoD = 调用链无第二默认值,tech-decisions §13);⑤ jar 轮换 = env 依赖面随升(NACOS_PASSWORD 双杀教训),部署/重启脚本同步改;⑥ 若触队列参数,rocketmq consumeThreadMax 是死参数,有效并发 = consumeThreadNumber 且 min=max。
**自审**:每步交付附真实 commit hash + 真跑验证输出(hash 会被 rev-parse 核验,伪造必露);没全绿报 BLOCKED、不谎报 DONE;激活一致性(§6 首条)是本单最重风险——实施中若发现投影层补偿语义做不到,停下挂问题、不许绕;收口时随上级 §6 收口单一并回写 §7 涟漪清单,不双开。
**执行终局(2026-07-04)**:§4 五步连同 namespace 前置全部代码落地(前置 `b2b4d389`、步骤 1+2 `3ae34de1`、步骤 3 `72973532`、步骤 4 `344330a4`+入口 `d9def7d9`、步骤 5 `a8dd5e50`),cheap 与 tier2 两档的 Service 入口都已接上双路激活的 PATCH 落点与 NacosHotConfig 热源;启用旗默认关,生产灰度与路 A 对真 Service 的 PATCH 排部署窗口(先门阈值、验稳再切预算目标)。实施中坐实三处口径修正、已就地回写正文:① AgentScope 没有单个 GET `/agent/{id}`,漂移对账改用 `/agent` 列表端点按 id 过滤(§3.6 早稿"拉 `/agent`"口径随此改真);② Nacos 是 publish→read 最终一致、非即时,对账读带 8s 容忍窗,避开刚激活尚未收敛的中间态被误报成漂移;③ 机器上遗留 env 覆盖压过激活值这类漂移从 game-cloud 侧看不见(env 只活在 worker 进程内),当前对账探不到,挂阶段四观测补——由 worker 暴露一个 effective 配置端点、把真正生效值连同来源吐出来供对账。§7 涟漪清单第 14 行已回写上级设计档(§0 / §3.3 / §3.6 图 / §3.7 / §4),收口标记见上级 §6;第 5 行 SoT 回写已随架构图说 doc-sync(2026-07-03)完成。余下待办承 §4 后续阶段:阶段三管理面 UI、阶段四观测、部署窗口灰度。
## 附 图清单与状态
| 图 | 角色 | 状态 |
|---|---|---|
| 图0 一图看懂 | §0 门面 SVG | 待出图 |
| 图1 配置中心分层与分工 | §2 / §3.1 / §3.5 分工边界与四方职责 | 已出图 `assets/cfgctl2-01-配置中心分层与分工.svg` |
| 图2 双路激活编排 | §3.3 双路下发编排(内联 Mermaid 事实源已在文) | 已出图 `assets/cfgctl2-02-双路激活编排.svg` |
| 图3 激活一致性状态机 | §3.2 生命周期 + §3.6 ACTIVATING 恢复(内联 Mermaid 事实源已在文) | 已出图 `assets/cfgctl2-03-激活一致性状态机.svg` |
| 图4 漂移对账三态 | §3.6 配置漂移检测三态 | 已出图 `assets/cfgctl2-04-漂移对账三态.svg` |
文字 + Mermaid 为事实源,SVG 为派生视觉。