docs(svg): 配置控制面阶段二 4 张人读 SVG(W-DSGN SVG 尾波核心)+ 接入阶段二设计档填占位
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled

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>
This commit is contained in:
lili 2026-07-05 01:43:41 -07:00
parent 4ff754c634
commit 8409f19c2a
5 changed files with 435 additions and 8 deletions

View File

@ -16,7 +16,7 @@ sot-impact: 修订 生成引擎运行时(SoT §5.2 管理面配置管理 / §5.8
- 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 失败模式与兜底]
图清单: [图0 一图看懂(待补), 图1 配置中心分层与分工, 图2 双路激活编排, 图3 激活一致性状态机, 图4 漂移对账三态]
---
# 配置控制面 · 阶段二:yudao 配置中心 · 功能设计
@ -50,7 +50,7 @@ sot-impact: 修订 生成引擎运行时(SoT §5.2 管理面配置管理 / §5.8
## 2 边界
(图1 分工边界 SVG 待补)
![图 1 · 配置中心分层与分工](assets/cfgctl2-01-配置中心分层与分工.svg)
进控制面的判据沿用 SoT §5.8 的配置三类;本阶段只碰其中"热配置策略类"里属于**生成业务**的那部分,并给它加治理。
@ -109,11 +109,13 @@ stateDiagram-v2
待审 --> 草稿: 驳回
```
![图 3 · 激活一致性状态机](assets/cfgctl2-03-激活一致性状态机.svg)
几个关键点。**激活之前 Nacos 完全不被触碰**:草稿与版本行都是 yudao 库内数据,配置内容到"激活"才第一次离开治理库——这天然堵死了"草稿提前生效"的口子(Nacos 的配置是 publish 即被监听者读到的,预算/阈值若提前进 Nacos 就绕过了激活闸)。**激活是独立的闸**:它把选定版本的内容双路下发(见 §3.3),并把"当前激活版指针"指过去。**回滚就是重放激活**:取历史版本行的内容,走一遍激活动作,幂等。**归因与审计随生命周期自然沉淀**:定版记 creator 与时间,激活/回滚是一条 yudao 操作日志,diff 是两条版本行的就地比对——全是 yudao 原生能力,不新造。
### 3.3 双路激活:PATCH 路 ⊕ Nacos 热读路
(图2 配置生命周期与双路激活 SVG 待补)
![图 2 · 双路激活编排](assets/cfgctl2-02-双路激活编排.svg)
激活一个配置集,编排层从选定的版本行取内容,按旋钮性质分两路下发:
@ -166,7 +168,7 @@ flowchart LR
### 3.6 失败模式与兜底
(图3 失败模式与兜底 SVG 待补)
![图 4 · 漂移对账三态](assets/cfgctl2-04-漂移对账三态.svg)
激活是一批跨系统的非原子写(PATCH Service + publish Nacos + 更新 yudao 指针),这里的失败模式要正面处理,不能让配置中心把生成链路带崩。
@ -289,9 +291,10 @@ flowchart LR
| 图 | 角色 | 状态 |
|---|---|---|
| 图0 一图看懂 | §0 门面 SVG | 待 opus 子代理出图 |
| 图1 分工边界与四方职责 | §2/§3.5 SVG | 待出图 |
| 图2 配置生命周期与双路激活 | §3.2/§3.3 SVG(内联 Mermaid 事实源已在文) | 待出图 |
| 图3 失败模式与兜底 | §3.6 SVG(内联 Mermaid 事实源已在文) | 待出图 |
| 图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 为派生视觉。

View File

@ -0,0 +1,124 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1480 884" font-family="-apple-system,'PingFang SC','Microsoft YaHei',Segoe UI,sans-serif">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#334155"/></marker>
<marker id="arrowP" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#7c3aed"/></marker>
<marker id="arrowR" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#dc2626"/></marker>
<marker id="arrowG" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#16a34a"/></marker>
<marker id="arrowA" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#2563eb"/></marker>
<marker id="arrowN" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#ca8a04"/></marker>
<style>
.t{fill:#0f172a}.mut{fill:#475569}.sm{font-size:12px}.xs{font-size:11px}.xxs{font-size:10px}
.h1{font-size:24px;font-weight:700}.h2{font-size:14px;font-weight:700}.lbl{font-size:13px;font-weight:600}
.flow{stroke:#334155;stroke-width:2;fill:none}.flowb{stroke:#64748b;stroke-width:1.6;fill:none;stroke-dasharray:6 4}
.flowp{stroke:#7c3aed;stroke-width:1.8;fill:none;stroke-dasharray:6 4}.flowr{stroke:#dc2626;stroke-width:2;fill:none}
.flowg{stroke:#16a34a;stroke-width:2;fill:none}.flowa{stroke:#2563eb;stroke-width:2;fill:none}.flown{stroke:#ca8a04;stroke-width:2;fill:none}
.badge{font-size:10.5px;font-weight:700}.fut{font-size:11px;font-weight:700;fill:#7c3aed}
</style>
</defs>
<rect x="0" y="0" width="1480" height="884" fill="#f8fafc"/>
<text x="40" y="38" class="t h1">图 1 · 配置中心分层与分工(yudao 版本账本 ⊕ Nacos 生效下发)</text>
<text x="40" y="58" class="mut sm">配置中心把职责劈两半、各用现货:yudao 管治理与版本账本(版本行落 MySQL),Nacos 管路 B 生效下发。谁改决定要不要治理;prompt 正文因 100KB 上限出 Nacos、进 MySQL 版本行。</text>
<rect x="40" y="72" width="1400" height="30" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.3"/>
<text x="54" y="92" class="t xs"><tspan font-weight="700">整图状态——</tspan><tspan fill="#15803d" font-weight="700">实线 = 现行已落地</tspan><tspan>(五步 2026-07-04 全落、mini-desktop 真机 smoke 验过) · </tspan><tspan fill="#7c3aed" font-weight="700">紫虚线 = 后续阶段</tspan><tspan>(阶段三 UI / 阶段四观测 / 放量后 BPM 审批)。业务生成配置与基建配置在 Nacos 上以命名空间隔离。</tspan></text>
<rect x="40" y="116" width="688" height="64" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-width="2.2"/>
<text x="56" y="140" class="h2" fill="#1d4ed8">yudao —— 治理与版本账本(权威)</text>
<text x="56" y="159" class="xs mut">版本行 = 全量内容(含 prompt · MEDIUMTEXT)+ 元数据</text>
<text x="56" y="175" class="xxs mut">当前激活版指针 · creator · 状态机 · 审批挂点 · 操作审计 · 激活编排</text>
<text x="726" y="155" class="h1" text-anchor="middle" fill="#475569">⊕</text>
<rect x="748" y="116" width="692" height="64" rx="10" fill="#fefce8" stroke="#ca8a04" stroke-width="2.2"/>
<text x="764" y="140" class="h2" fill="#a16207">Nacos —— 路 B 生效下发通道</text>
<text x="764" y="159" class="xs mut">publish 预算 / 门阈值到生效 dataId(按档隔离)· worker 长轮询热读</text>
<text x="764" y="175" class="xxs mut">不承版本账本(生效 dataId 上的历史只是排障留痕、非权威)</text>
<rect x="40" y="198" width="110" height="30" rx="8" fill="#e2e8f0" stroke="#94a3b8" stroke-width="1.1"/>
<text x="95" y="218" class="xs" text-anchor="middle" font-weight="700">分工边界</text>
<rect x="150" y="198" width="630" height="30" rx="8" fill="#fefce8" stroke="#ca8a04" stroke-width="1.1"/>
<text x="160" y="218" class="xs" font-weight="700" fill="#a16207">基建配置 —— 不进本治理层(阶段〇已接,运维改即时热生效)</text>
<rect x="780" y="198" width="660" height="30" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.1"/>
<text x="790" y="218" class="xs" font-weight="700" fill="#1d4ed8">业务生成配置 —— 受治理版本化(本阶段治理对象)</text>
<rect x="40" y="228" width="110" height="38" rx="8" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1.0"/>
<text x="95" y="251" class="xs" text-anchor="middle" font-weight="700" fill="#334155">例子</text>
<rect x="150" y="228" width="630" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="160" y="251" class="xs" fill="#334155">game-cloud Spring 配置 · Sentinel 流控规则 · RocketMQ 参数 · 服务发现</text>
<rect x="780" y="228" width="660" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="790" y="251" class="xs" fill="#334155">prompt · 模型 · 参数 · 软预算目标 · 门阈值档</text>
<rect x="40" y="266" width="110" height="38" rx="8" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1.0"/>
<text x="95" y="289" class="xs" text-anchor="middle" font-weight="700" fill="#334155">谁改</text>
<rect x="150" y="266" width="630" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="160" y="289" class="xs" fill="#334155">运维 / 开发</text>
<rect x="780" y="266" width="660" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="790" y="289" class="xs" fill="#334155">创始人 / 运营</text>
<rect x="40" y="304" width="110" height="38" rx="8" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1.0"/>
<text x="95" y="327" class="xs" text-anchor="middle" font-weight="700" fill="#334155">要不要治理</text>
<rect x="150" y="304" width="630" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="160" y="327" class="xs" fill="#334155">不要 —— 即时热生效即可</text>
<rect x="780" y="304" width="660" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="790" y="327" class="xs" fill="#334155">要 —— 版本 / 审计 / 审批 / 可回滚</text>
<rect x="40" y="342" width="110" height="38" rx="8" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1.0"/>
<text x="95" y="365" class="xs" text-anchor="middle" font-weight="700" fill="#334155">通路</text>
<rect x="150" y="342" width="630" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="160" y="365" class="xs" fill="#334155">Nacos SCA 原生(dataId 按应用名 · @RefreshScope 或重启)</text>
<rect x="780" y="342" width="660" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="790" y="365" class="xs" fill="#334155">yudao 治理层(MySQL 版本行为账本)→ 激活时 PATCH Service、publish 生效 dataId(双路)</text>
<rect x="40" y="380" width="110" height="38" rx="8" fill="#f1f5f9" stroke="#cbd5e1" stroke-width="1.0"/>
<text x="95" y="403" class="xs" text-anchor="middle" font-weight="700" fill="#334155">消费方</text>
<rect x="150" y="380" width="630" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="160" y="403" class="xs" fill="#334155">game-cloud 各 Java 服务</text>
<rect x="780" y="380" width="660" height="38" rx="8" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.0"/>
<text x="790" y="403" class="xs" fill="#334155">AgentScope Service(路 A PATCH)+ Python worker(路 B NacosHotConfig)</text>
<rect x="40" y="432" width="1400" height="104" rx="10" fill="#f1f5f9" stroke="#475569" stroke-width="1.6"/>
<text x="56" y="454" class="h2">账本单点 · 投影两处 · 消费两路(权威 → 投影 → 消费)</text>
<rect x="56" y="464" width="286" height="60" rx="8" fill="#eef2ff" stroke="#4338ca" stroke-width="1.8"/>
<text x="66" y="484" class="lbl">账本单点(权威)</text>
<text x="66" y="502" class="xxs mut">yudao MySQL 版本行</text>
<text x="66" y="516" class="xxs mut">全量含 prompt · 当前激活版指针</text>
<rect x="430" y="462" width="304" height="30" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="1.3"/>
<text x="440" y="482" class="xs">路 A 投影:AgentScope Service 的 Redis</text>
<rect x="430" y="496" width="304" height="30" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.3"/>
<text x="440" y="516" class="xs">路 B 投影:worker genconfig(NacosHotConfig)</text>
<rect x="770" y="462" width="314" height="30" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="1.3"/>
<text x="780" y="482" class="xs">消费:每 POST /chat 现装配读出(热)</text>
<rect x="770" y="496" width="314" height="30" rx="8" fill="#ffffff" stroke="#ca8a04" stroke-width="1.3"/>
<text x="780" y="516" class="xs">消费:middleware 构造时读(软预算 / 门判)</text>
<rect x="1098" y="462" width="326" height="64" rx="8" fill="#ecfeff" stroke="#0891b2" stroke-width="1.4"/>
<text x="1108" y="480" class="xs" font-weight="700" fill="#155e75">权威 vs 投影</text>
<text x="1108" y="497" class="xxs mut">账本单点(MySQL 版本行)· 投影两处</text>
<text x="1108" y="512" class="xxs mut">(Redis / Nacos dataId)· 漂移对账见图 4</text>
<line x1="342" y1="494" x2="388" y2="477" class="flowa" marker-end="url(#arrowA)"/>
<line x1="342" y1="494" x2="388" y2="511" class="flown" marker-end="url(#arrowN)"/>
<line x1="734" y1="477" x2="766" y2="477" class="flowa" marker-end="url(#arrowA)"/>
<line x1="734" y1="511" x2="766" y2="511" class="flown" marker-end="url(#arrowN)"/>
<rect x="40" y="552" width="1400" height="158" rx="10" fill="#fff7ed" stroke="#d97706" stroke-width="1.6"/>
<text x="56" y="574" class="h2" fill="#b45309">prompt 正文为何出 Nacos、进 MySQL 版本行(创始人拍 B 时点名要解)</text>
<rect x="56" y="582" width="440" height="76" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="66" y="602" class="lbl">① 放不进 Nacos</text>
<text x="66" y="620" class="xxs mut">单配置默认上限 100KB;system_prompt 连 few-shot、</text>
<text x="66" y="635" class="xxs mut">多角色随版本行增长向上限爬(现最大单条 14.7KB)</text>
<text x="66" y="650" class="xxs mut">把最勤改的旋钮放上限边缘,不如换地方</text>
<rect x="516" y="582" width="440" height="76" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="526" y="602" class="lbl">② 定版要原子</text>
<text x="526" y="620" class="xxs mut">版本行(元数据 + 全量内容)同库同事务一次落</text>
<text x="526" y="635" class="xxs mut">内容一旦出库即成跨系统写、必漂移</text>
<text x="526" y="650" class="xxs mut">治理层最高频动作不该是分布式事务</text>
<rect x="976" y="582" width="448" height="76" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="986" y="602" class="lbl">③ diff 与检索要就地</text>
<text x="986" y="620" class="xxs mut">版本 diff、按内容查历史都是版本行本地操作</text>
<text x="986" y="635" class="xxs mut">内容在外部系统则每次 diff 都要来回取对象</text>
<text x="986" y="650" class="xxs mut">两版 diff 在应用层做</text>
<rect x="56" y="666" width="1368" height="30" rx="8" fill="#ffedd5" stroke="#d97706" stroke-width="1.2"/>
<text x="66" y="686" class="xs" font-weight="700" fill="#7c2d12">结论:prompt 正文列定 MySQL MEDIUMTEXT(16MB)、不落 Nacos 也不落 MinIO;Nacos 收窄为路 B 生效下发通道、不承版本账本。</text>
<text x="40" y="748" class="h2">图例:</text>
<rect x="100" y="734" width="30" height="18" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.8"/>
<text x="138" y="748" class="xs">业务生成配置 / 路 A(yudao · Redis)</text>
<rect x="420" y="734" width="30" height="18" rx="8" fill="#fefce8" stroke="#ca8a04" stroke-width="1.8"/>
<text x="458" y="748" class="xs">基建 / 路 B 生效下发(Nacos)</text>
<rect x="720" y="734" width="30" height="18" rx="8" fill="#fff7ed" stroke="#d97706" stroke-width="1.8"/>
<text x="758" y="748" class="xs">关键约束 / 边界说明</text>
<rect x="1006" y="733" width="52" height="18" rx="3" fill="#475569"/>
<text x="1032.0" y="746" class="badge" text-anchor="middle" fill="#fff">数据</text>
<rect x="1064" y="733" width="52" height="18" rx="3" fill="#dc2626"/>
<text x="1090.0" y="746" class="badge" text-anchor="middle" fill="#fff">安全</text>
<text x="1126" y="748" class="xs mut">版本账本 = 数据治理 · 权限 / 审批 = 安全</text>
<text x="40" y="788" class="mut xs">读这张图抓三点:① 配置中心两半 —— yudao 管治理与版本账本、Nacos 管路 B 生效下发,各用现货、不自建下发机制;</text>
<text x="40" y="806" class="mut xs">② 谁改决定要不要治理 —— 运维 / 开发改基建配置走 Nacos SCA 原生,创始人 / 运营改业务生成配置走 yudao 受治理;③ prompt 正文因 100KB 上限、定版原子、就地 diff 三条,落 MySQL MEDIUMTEXT、不落 Nacos。</text>
<text x="40" y="854" class="mut xs">映射:本档 §3.1 配置中心两半 · §3.5 分工边界 · §附 图1 | 状态:现(五步已落地 2026-07-04)+ 建(阶段三 UI / 阶段四观测 / 放量后 BPM)| 设计变动须同步本图</text>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,106 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1480 812" font-family="-apple-system,'PingFang SC','Microsoft YaHei',Segoe UI,sans-serif">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#334155"/></marker>
<marker id="arrowP" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#7c3aed"/></marker>
<marker id="arrowR" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#dc2626"/></marker>
<marker id="arrowG" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#16a34a"/></marker>
<marker id="arrowA" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#2563eb"/></marker>
<marker id="arrowN" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#ca8a04"/></marker>
<style>
.t{fill:#0f172a}.mut{fill:#475569}.sm{font-size:12px}.xs{font-size:11px}.xxs{font-size:10px}
.h1{font-size:24px;font-weight:700}.h2{font-size:14px;font-weight:700}.lbl{font-size:13px;font-weight:600}
.flow{stroke:#334155;stroke-width:2;fill:none}.flowb{stroke:#64748b;stroke-width:1.6;fill:none;stroke-dasharray:6 4}
.flowp{stroke:#7c3aed;stroke-width:1.8;fill:none;stroke-dasharray:6 4}.flowr{stroke:#dc2626;stroke-width:2;fill:none}
.flowg{stroke:#16a34a;stroke-width:2;fill:none}.flowa{stroke:#2563eb;stroke-width:2;fill:none}.flown{stroke:#ca8a04;stroke-width:2;fill:none}
.badge{font-size:10.5px;font-weight:700}.fut{font-size:11px;font-weight:700;fill:#7c3aed}
</style>
</defs>
<rect x="0" y="0" width="1480" height="812" fill="#f8fafc"/>
<text x="40" y="38" class="t h1">图 2 · 双路激活编排(sanity 前置 → 快照 → 双路下发 → 指针前移)</text>
<text x="40" y="58" class="mut sm">激活一次 = 值域 sanity 前置拒发 → beginActivating 快照(单库事务)→ 路 A PATCH 与 路 B publish 并行下发 → 全成才 markVersionActivated 指针前移;任一步败即整批判未生效、立即补偿重推已成功路回上一激活版。</text>
<rect x="40" y="72" width="1400" height="30" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.3"/>
<text x="54" y="92" class="t xs"><tspan font-weight="700">整图状态——</tspan><tspan fill="#15803d" font-weight="700">实线 = 现行已落地</tspan><tspan>(步骤 3 双路激活 72973532、路 A 复数端点修复 22444fd5) · </tspan><tspan fill="#dc2626" font-weight="700">红线 = 失败补偿路</tspan><tspan>。跨系统非原子、投影写即被读:不承诺投影层原子,靠即时补偿收敛。</tspan></text>
<rect x="40" y="116" width="182" height="56" rx="8" fill="#e2e8f0" stroke="#0f172a" stroke-width="1.6"/>
<text x="50" y="139" class="lbl">触发</text>
<text x="50" y="158" class="xxs mut">yudao 选定一版本发起激活</text>
<rect x="252" y="116" width="392" height="56" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.6"/>
<text x="262" y="137" class="lbl" fill="#1d4ed8">① sanity 值域前置拒发</text>
<text x="262" y="154" class="xxs mut">预算正数落区间·单位固定 / 超时有下限 / max_tokens > thinking</text>
<text x="262" y="167" class="xxs mut">/ 模型 type 配 credential / prompt 非空 —— 不过即拒、不下发</text>
<rect x="674" y="116" width="372" height="56" rx="8" fill="#eef2ff" stroke="#4338ca" stroke-width="1.6"/>
<text x="684" y="137" class="lbl" fill="#3730a3">② beginActivating 快照</text>
<text x="684" y="154" class="xxs mut">下发前先把激活态落 ACTIVATING</text>
<text x="684" y="167" class="xxs mut">(单库事务 · V30 持久中间态)</text>
<line x1="222" y1="144" x2="250" y2="144" class="flow" marker-end="url(#arrow)"/>
<line x1="644" y1="144" x2="672" y2="144" class="flow" marker-end="url(#arrow)"/>
<line x1="860" y1="172" x2="860" y2="206" class="flow" marker-end="url(#arrow)"/>
<text x="872" y="196" class="xxs mut">双路并行下发</text>
<rect x="40" y="210" width="1400" height="92" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-width="1.8"/>
<text x="56" y="232" class="h2" fill="#1d4ed8">路 A · prompt / 模型 / 参数 —— PATCH 写 Service Redis(下一 POST 现装配即生效)</text>
<rect x="56" y="242" width="316" height="44" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="1.3"/>
<text x="66" y="262" class="xs" font-weight="600">PATCH /agent</text>
<text x="66" y="278" class="xxs mut">system_prompt · 压缩比 · 截断 · max_iters</text>
<rect x="402" y="242" width="356" height="44" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="1.3"/>
<text x="412" y="262" class="xs" font-weight="600">PATCH /sessions</text>
<text x="412" y="278" class="xxs mut">模型 · type · credential · max_tokens · thinking</text>
<rect x="788" y="242" width="236" height="44" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="1.3"/>
<text x="798" y="262" class="xs" font-weight="600">AgentScope Redis</text>
<text x="798" y="278" class="xxs mut">当前配置投影</text>
<rect x="1054" y="242" width="236" height="44" rx="8" fill="#ffffff" stroke="#2563eb" stroke-width="1.3"/>
<text x="1064" y="262" class="xs" font-weight="600">下一 POST /chat</text>
<text x="1064" y="278" class="xxs mut">现装配读出、热生效</text>
<line x1="372" y1="264" x2="400" y2="264" class="flowa" marker-end="url(#arrowA)"/>
<line x1="758" y1="264" x2="786" y2="264" class="flowa" marker-end="url(#arrowA)"/>
<line x1="1024" y1="264" x2="1052" y2="264" class="flowa" marker-end="url(#arrowA)"/>
<rect x="40" y="316" width="1400" height="92" rx="10" fill="#fefce8" stroke="#ca8a04" stroke-width="1.8"/>
<text x="56" y="338" class="h2" fill="#a16207">路 B · 软预算目标 / 门阈值 —— publish Nacos 生效 dataId(worker 长轮询热读)</text>
<rect x="56" y="348" width="316" height="44" rx="8" fill="#ffffff" stroke="#ca8a04" stroke-width="1.3"/>
<text x="66" y="368" class="xs" font-weight="600">publish 生效 dataId</text>
<text x="66" y="384" class="xxs mut">按档隔离 · 只发本档</text>
<rect x="402" y="348" width="316" height="44" rx="8" fill="#ffffff" stroke="#ca8a04" stroke-width="1.3"/>
<text x="412" y="368" class="xs" font-weight="600">NacosHotConfig</text>
<text x="412" y="384" class="xxs mut">长轮询推送热读进进程</text>
<rect x="748" y="348" width="216" height="44" rx="8" fill="#ffffff" stroke="#ca8a04" stroke-width="1.3"/>
<text x="758" y="368" class="xs" font-weight="600">genconfig 门面</text>
<text x="758" y="384" class="xxs mut">热源投影</text>
<rect x="994" y="348" width="256" height="44" rx="8" fill="#ffffff" stroke="#ca8a04" stroke-width="1.3"/>
<text x="1004" y="368" class="xs" font-weight="600">middleware 构造时读</text>
<text x="1004" y="384" class="xxs mut">软预算 / 门判取新值</text>
<line x1="372" y1="370" x2="400" y2="370" class="flown" marker-end="url(#arrowN)"/>
<line x1="718" y1="370" x2="746" y2="370" class="flown" marker-end="url(#arrowN)"/>
<line x1="964" y1="370" x2="992" y2="370" class="flown" marker-end="url(#arrowN)"/>
<line x1="360" y1="408" x2="360" y2="428" class="flow" marker-end="url(#arrow)"/>
<line x1="1300" y1="302" x2="1300" y2="428" class="flow" marker-end="url(#arrow)"/>
<rect x="300" y="430" width="1020" height="48" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.9"/>
<text x="810" y="450" class="lbl" text-anchor="middle" fill="#166534">④ 双路全成 → markVersionActivated 指针前移 → 状态转 ACTIVE</text>
<text x="810" y="468" class="xxs mut" text-anchor="middle">当前激活版指针只在整批成功后前移;成组下发幂等,静默期只对下一批新生成生效</text>
<rect x="40" y="500" width="1400" height="52" rx="10" fill="#fef2f2" stroke="#dc2626" stroke-width="1.7"/>
<text x="56" y="521" class="xs" font-weight="700" fill="#b91c1c">✕ 任一步失败(某 PATCH 返错 / Nacos publish 超时 / Service 不可达)</text>
<text x="56" y="540" class="xs mut">→ 整批判未生效(当前激活版指针不前移)→ 立即补偿:把已成功下发的那一路重推回上一激活版 → 标可重试(补偿与重放幂等)</text>
<line x1="810" y1="478" x2="810" y2="498" class="flowr" marker-end="url(#arrowR)"/>
<text x="822" y="492" class="xxs" font-weight="700" fill="#b91c1c">任一步败</text>
<rect x="40" y="568" width="690" height="72" rx="9" fill="#f1f5f9" stroke="#475569" stroke-width="1.4"/>
<text x="56" y="588" class="lbl">静默期语义(为何并发几乎不撕裂)</text>
<text x="56" y="606" class="xxs mut">两路生效都落在「下一次生成」边界:路 A 的 Redis 在进 session 锁前读、</text>
<text x="56" y="620" class="xxs mut">路 B 的 genconfig 在 middleware 构造时读,正跑的那局早已读过配置。唯一</text>
<text x="56" y="634" class="xxs mut">撕裂窗口 = 激活自身中途失败(投影写即被读、无事务),靠即时补偿收敛。</text>
<rect x="750" y="568" width="690" height="72" rx="9" fill="#f1f5f9" stroke="#475569" stroke-width="1.4"/>
<text x="766" y="588" class="lbl">两处必须定死的下发口径</text>
<text x="766" y="606" class="xxs mut">路 A:改任一模型参数都要从版本行组装完整 chat_model_config</text>
<text x="766" y="620" class="xxs mut">(整体替换、顶层 exclude_unset 不深合并内部 parameters)。</text>
<text x="766" y="634" class="xxs mut">路 B:生效 dataId 按档隔离(cheap_rmb_hard_limit / rmb_hard_limit),激活哪档只发哪档。</text>
<text x="40" y="680" class="h2">图例:</text>
<line x1="100" y1="674" x2="150" y2="674" class="flowa" marker-end="url(#arrowA)"/>
<text x="158" y="680" class="xs">路 A(PATCH → Service Redis)</text>
<line x1="400" y1="674" x2="450" y2="674" class="flown" marker-end="url(#arrowN)"/>
<text x="458" y="680" class="xs">路 B(publish → Nacos 热读)</text>
<line x1="700" y1="674" x2="750" y2="674" class="flowg" marker-end="url(#arrowG)"/>
<text x="758" y="680" class="xs">双路全成、指针前移</text>
<line x1="980" y1="674" x2="1030" y2="674" class="flowr" marker-end="url(#arrowR)"/>
<text x="1038" y="680" class="xs">失败 → 补偿重推回上一激活版</text>
<rect x="1330" y="663" width="52" height="18" rx="3" fill="#16a34a"/>
<text x="1356.0" y="676" class="badge" text-anchor="middle" fill="#fff">可靠</text>
<text x="40" y="720" class="mut xs">读这张图抓三点:① 激活是独立的闸 —— sanity 校验拦住语义非法值(负预算等)、快照先落 ACTIVATING,再双路并行下发;</text>
<text x="40" y="738" class="mut xs">② 权威只在双路全成后前移,任一步败即判未生效并立即补偿,不留「路 A 新、路 B 旧」的持续撕裂;③ 并发撕裂由静默期规避,机制级原子(epoch 戳)留放量后。</text>
<text x="40" y="780" class="mut xs">映射:本档 §3.3 双路激活 · §4 步骤 3 · tech-decisions §14(激活一致性落地形态)| 状态:现(72973532 / 22444fd5)· 机制级原子留放量后 | 设计变动须同步本图</text>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,85 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1480 690" font-family="-apple-system,'PingFang SC','Microsoft YaHei',Segoe UI,sans-serif">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#334155"/></marker>
<marker id="arrowP" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#7c3aed"/></marker>
<marker id="arrowR" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#dc2626"/></marker>
<marker id="arrowG" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#16a34a"/></marker>
<marker id="arrowA" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#2563eb"/></marker>
<marker id="arrowN" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#ca8a04"/></marker>
<style>
.t{fill:#0f172a}.mut{fill:#475569}.sm{font-size:12px}.xs{font-size:11px}.xxs{font-size:10px}
.h1{font-size:24px;font-weight:700}.h2{font-size:14px;font-weight:700}.lbl{font-size:13px;font-weight:600}
.flow{stroke:#334155;stroke-width:2;fill:none}.flowb{stroke:#64748b;stroke-width:1.6;fill:none;stroke-dasharray:6 4}
.flowp{stroke:#7c3aed;stroke-width:1.8;fill:none;stroke-dasharray:6 4}.flowr{stroke:#dc2626;stroke-width:2;fill:none}
.flowg{stroke:#16a34a;stroke-width:2;fill:none}.flowa{stroke:#2563eb;stroke-width:2;fill:none}.flown{stroke:#ca8a04;stroke-width:2;fill:none}
.badge{font-size:10.5px;font-weight:700}.fut{font-size:11px;font-weight:700;fill:#7c3aed}
</style>
</defs>
<rect x="0" y="0" width="1480" height="690" fill="#f8fafc"/>
<text x="40" y="38" class="t h1">图 3 · 激活一致性状态机(草稿 → 待审 → 激活中 → 已激活)</text>
<text x="40" y="58" class="mut sm">配置集的生命周期。激活前 Nacos 完全不被触碰;ACTIVATING 是 V30 持久中间态,账本提交失败留在此态由 recoverActivating 幂等收口;恢复语义按失败点位分「向前执行到底」与「补偿回退」两支。</text>
<rect x="40" y="70" width="1400" height="30" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.3"/>
<text x="54" y="90" class="t xs"><tspan font-weight="700">整图状态——</tspan><tspan fill="#15803d" font-weight="700">实线 = 现行已落地</tspan><tspan>(治理子域 Flyway V29 / V30 · 步骤 1+2 3ae34de1) · </tspan><tspan fill="#7c3aed" font-weight="700">紫虚线 = 后续阶段</tspan><tspan>。MVP 创始人角色由待审直接激活、审批自动通过;放量后打开 BPM 审批,同一状态机不改。</tspan></text>
<rect x="50" y="206" width="190" height="64" rx="12" fill="#f1f5f9" stroke="#64748b" stroke-width="2.0"/>
<text x="145.0" y="233" class="lbl" text-anchor="middle">草稿</text>
<text x="145.0" y="252" class="xxs mut" text-anchor="middle">yudao 库内数据</text>
<rect x="330" y="206" width="190" height="64" rx="12" fill="#fef9c3" stroke="#ca8a04" stroke-width="2.0"/>
<text x="425.0" y="233" class="lbl" text-anchor="middle">待审</text>
<text x="425.0" y="252" class="xxs mut" text-anchor="middle">版本行已落库</text>
<rect x="610" y="206" width="190" height="64" rx="12" fill="#ffedd5" stroke="#ea580c" stroke-width="2.4"/>
<text x="705.0" y="233" class="lbl" text-anchor="middle" fill="#c2410c">激活中 ACTIVATING</text>
<text x="705.0" y="252" class="xxs mut" text-anchor="middle">V30 持久中间态</text>
<rect x="950" y="206" width="190" height="64" rx="12" fill="#dcfce7" stroke="#16a34a" stroke-width="2.0"/>
<text x="1045.0" y="233" class="lbl" text-anchor="middle">已激活</text>
<text x="1045.0" y="252" class="xxs mut" text-anchor="middle">当前激活版指针</text>
<rect x="1240" y="206" width="190" height="64" rx="12" fill="#e2e8f0" stroke="#94a3b8" stroke-width="2.0"/>
<text x="1335.0" y="233" class="lbl" text-anchor="middle">已归档</text>
<text x="1335.0" y="252" class="xxs mut" text-anchor="middle">被取代归档</text>
<text x="58" y="194" class="xxs mut">起点 ●</text>
<line x1="80" y1="198" x2="80" y2="204" class="flow" marker-end="url(#arrow)"/>
<line x1="240" y1="238" x2="328" y2="238" class="flow" marker-end="url(#arrow)"/>
<text x="285.0" y="230" class="xxs" text-anchor="middle" font-weight="700" fill="#334155">定版</text>
<line x1="520" y1="238" x2="608" y2="238" class="flow" marker-end="url(#arrow)"/>
<text x="565.0" y="230" class="xxs" text-anchor="middle" font-weight="700" fill="#334155">审核通过·发起激活</text>
<line x1="800" y1="238" x2="948" y2="238" class="flow" marker-end="url(#arrow)"/>
<text x="875.0" y="230" class="xxs" text-anchor="middle" font-weight="700" fill="#334155">双路全成·指针前移</text>
<line x1="1140" y1="238" x2="1238" y2="238" class="flow" marker-end="url(#arrow)"/>
<text x="1190.0" y="230" class="xxs" text-anchor="middle" font-weight="700" fill="#334155">被更新版本取代</text>
<path d="M 665 206 C 640 166, 770 166, 745 204" class="flowp" marker-end="url(#arrowP)"/>
<text x="705" y="146" class="xxs mut" text-anchor="middle">recoverActivating 幂等向前收口</text>
<text x="705" y="160" class="xxs" text-anchor="middle" font-weight="700" fill="#7c3aed">账本提交失败·留 ACTIVATING</text>
<path d="M 1020 206 C 1000 168, 1110 168, 1090 204" class="flow" marker-end="url(#arrow)"/>
<text x="1055" y="158" class="xxs" text-anchor="middle" font-weight="700" fill="#334155">回滚 = 取历史版本行·重放激活(幂等)</text>
<path d="M 350 270 C 322 310, 244 310, 232 272" class="flowr" marker-end="url(#arrowR)"/>
<text x="290" y="304" class="xxs" text-anchor="middle" font-weight="700" fill="#b91c1c">驳回</text>
<path d="M 990 270 C 940 328, 500 328, 490 272" class="flowb" marker-end="url(#arrowB)"/>
<text x="715" y="300" class="xxs" text-anchor="middle" font-weight="700" fill="#475569">编辑出新版本</text>
<rect x="40" y="338" width="1130" height="44" rx="9" fill="#eff6ff" stroke="#2563eb" stroke-width="1.4"/>
<text x="56" y="356" class="xs" font-weight="700" fill="#1d4ed8">激活之前 Nacos 完全不被触碰</text>
<text x="300" y="356" class="xs mut">—— 草稿与版本行都是 yudao 库内数据,内容到「激活」才第一次离开治理库,天然堵死「草稿提前生效」。</text>
<text x="56" y="374" class="xxs mut">激活是独立的闸:把选定版内容双路下发,并把「当前激活版指针」指过去;回滚就是重放激活(幂等)。</text>
<rect x="40" y="396" width="1400" height="150" rx="10" fill="#fff7ed" stroke="#ea580c" stroke-width="1.6"/>
<text x="56" y="420" class="h2" fill="#c2410c">ACTIVATING 的两种恢复语义(按失败点位分开、不混用)</text>
<rect x="56" y="434" width="676" height="96" rx="8" fill="#ffffff" stroke="#16a34a" stroke-width="1.5"/>
<text x="66" y="454" class="lbl" fill="#166534">向前执行到底(补提交指针)</text>
<text x="66" y="474" class="xs mut">失败点位:三路投影(PATCH /agent · PATCH /sessions · publish Nacos)</text>
<text x="66" y="488" class="xs mut">都已成功、只差最后前移指针或写审计时 MySQL 失败。</text>
<text x="66" y="508" class="xs" font-weight="600" fill="#166534">→ 投影既已是新版,recoverActivating 补提交指针、对齐账本。</text>
<rect x="748" y="434" width="676" height="96" rx="8" fill="#ffffff" stroke="#dc2626" stroke-width="1.5"/>
<text x="758" y="454" class="lbl" fill="#b91c1c">补偿回退(重推旧版)</text>
<text x="758" y="474" class="xs mut">失败点位:某一路投影下发失败,双路没能全成。</text>
<text x="758" y="488" class="xs mut">此刻不能把半生效态留在投影层。</text>
<text x="758" y="508" class="xs" font-weight="600" fill="#b91c1c">→ 补偿重推上一激活版回投影 + 回滚该激活尝试,收敛回旧版。</text>
<text x="40" y="584" class="h2">图例:</text>
<line x1="100" y1="578" x2="150" y2="578" class="flow" marker-end="url(#arrow)"/>
<text x="158" y="584" class="xs">正常流转 / 回滚(幂等)</text>
<line x1="400" y1="578" x2="450" y2="578" class="flowr" marker-end="url(#arrowR)"/>
<text x="458" y="584" class="xs">驳回 / 补偿回退</text>
<line x1="700" y1="578" x2="750" y2="578" class="flowp" marker-end="url(#arrowP)"/>
<text x="758" y="584" class="xs">留 ACTIVATING · 幂等向前收口</text>
<line x1="1050" y1="578" x2="1100" y2="578" class="flowb" marker-end="url(#arrowB)"/>
<text x="1108" y="584" class="xs">编辑出新版本(回边)</text>
<text x="40" y="624" class="mut xs">读这张图抓三点:① 状态机把「编辑中」与「已生效」用一道激活闸分开,激活前 Nacos 不被触碰、堵死草稿提前生效;</text>
<text x="40" y="642" class="mut xs">② ACTIVATING 是持久中间态(V30),账本提交失败不回滚成前态、留在此态向前收口;③ 恢复按失败点位二选一 —— 投影全成则补提交指针、投影没全成则补偿重推旧版,绝不停在中间态。</text>
<text x="40" y="676" class="mut xs">映射:本档 §3.2 生命周期 · §3.6 ACTIVATING 恢复 · tech-decisions §14(激活一致性落地形态)| 状态:现(Flyway V29 / V30 · 3ae34de1)· 放量后接 BPM 审批 | 设计变动须同步本图</text>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,109 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1480 812" font-family="-apple-system,'PingFang SC','Microsoft YaHei',Segoe UI,sans-serif">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#334155"/></marker>
<marker id="arrowP" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#7c3aed"/></marker>
<marker id="arrowR" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#dc2626"/></marker>
<marker id="arrowG" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#16a34a"/></marker>
<marker id="arrowA" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#2563eb"/></marker>
<marker id="arrowN" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L8,3 L0,6 Z" fill="#ca8a04"/></marker>
<style>
.t{fill:#0f172a}.mut{fill:#475569}.sm{font-size:12px}.xs{font-size:11px}.xxs{font-size:10px}
.h1{font-size:24px;font-weight:700}.h2{font-size:14px;font-weight:700}.lbl{font-size:13px;font-weight:600}
.flow{stroke:#334155;stroke-width:2;fill:none}.flowb{stroke:#64748b;stroke-width:1.6;fill:none;stroke-dasharray:6 4}
.flowp{stroke:#7c3aed;stroke-width:1.8;fill:none;stroke-dasharray:6 4}.flowr{stroke:#dc2626;stroke-width:2;fill:none}
.flowg{stroke:#16a34a;stroke-width:2;fill:none}.flowa{stroke:#2563eb;stroke-width:2;fill:none}.flown{stroke:#ca8a04;stroke-width:2;fill:none}
.badge{font-size:10.5px;font-weight:700}.fut{font-size:11px;font-weight:700;fill:#7c3aed}
</style>
</defs>
<rect x="0" y="0" width="1480" height="812" fill="#f8fafc"/>
<text x="40" y="38" class="t h1">图 4 · 漂移对账三态(IN_SYNC / DRIFT / 不可达)</text>
<text x="40" y="58" class="mut sm">配置中心为权威、Service 与 worker 为投影;对账拉投影比对当前激活版,判 IN_SYNC / DRIFT 逐项 / 不可达三态。对账是兜底闸(第一道防线是即时补偿),读带 8s 容忍窗避开 Nacos 收敛中间态。</text>
<rect x="40" y="72" width="1400" height="30" rx="8" fill="#eff6ff" stroke="#2563eb" stroke-width="1.3"/>
<text x="54" y="92" class="t xs"><tspan font-weight="700">整图状态——</tspan><tspan fill="#15803d" font-weight="700">实线 = 现行已落地</tspan><tspan>(步骤 5 漂移对账 a8dd5e50 · 8s 容忍窗) · </tspan><tspan fill="#7c3aed" font-weight="700">紫虚线 = 阶段四观测补</tspan><tspan>。env 覆盖压过激活值这类漂移从 game-cloud 侧看不见,当前对账探不到,挂阶段四 worker effective 端点。</tspan></text>
<rect x="40" y="120" width="300" height="150" rx="10" fill="#eef2ff" stroke="#4338ca" stroke-width="1.9"/>
<text x="56" y="144" class="h2" fill="#3730a3">权威 · 当前激活版</text>
<rect x="56" y="158" width="268" height="44" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="1.3"/>
<text x="66" y="178" class="xs" font-weight="600">路 A 内容</text>
<text x="66" y="194" class="xxs mut">prompt / 模型 / 参数(PATCH 目标)</text>
<rect x="56" y="208" width="268" height="44" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.3"/>
<text x="66" y="228" class="xs" font-weight="600">路 B 内容</text>
<text x="66" y="244" class="xxs mut">软预算目标 / 门阈值(dataId 目标)</text>
<rect x="384" y="120" width="506" height="150" rx="10" fill="#f1f5f9" stroke="#475569" stroke-width="1.7"/>
<text x="400" y="144" class="h2">对账动作(激活后 + 定期)</text>
<text x="400" y="168" class="xs mut">拉 Service /agent(列表端点按 id 过滤,无单个 GET /agent/{id})</text>
<text x="400" y="184" class="xs mut">+ /sessions 当前配置 → 比对权威路 A 内容</text>
<text x="400" y="206" class="xs mut">拉 worker 生效投影 → 比对权威路 B 内容</text>
<text x="400" y="222" class="xs mut">(含 env 覆盖口径:实际生效值来自 env 而非激活版也算漂移)</text>
<rect x="400" y="232" width="474" height="28" rx="8" fill="#e0f2fe" stroke="#0284c7" stroke-width="1.3"/>
<text x="410" y="250" class="xs" fill="#075985">读带 8s 容忍窗(+800ms 步进)· 避开 Nacos publish→read 收敛中间态</text>
<line x1="340" y1="195" x2="382" y2="195" class="flow" marker-end="url(#arrow)"/>
<rect x="934" y="120" width="506" height="150" rx="10" fill="#ffffff" stroke="#94a3b8" stroke-width="1.5"/>
<text x="950" y="144" class="h2">对账判定三态</text>
<rect x="950" y="156" width="474" height="32" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
<text x="960" y="176" class="xs" font-weight="700" fill="#166534">IN_SYNC —— 投影 = 当前激活版</text>
<rect x="950" y="192" width="474" height="40" rx="8" fill="#fee2e2" stroke="#dc2626" stroke-width="1.5"/>
<text x="960" y="209" class="xs" font-weight="700" fill="#b91c1c">DRIFT(逐项)—— 某旋钮投影 ≠ 激活版</text>
<text x="960" y="225" class="xxs mut">逐旋钮列出差异;含 env 覆盖压过激活值</text>
<rect x="950" y="236" width="474" height="26" rx="8" fill="#e2e8f0" stroke="#64748b" stroke-width="1.5"/>
<text x="960" y="254" class="xs" font-weight="700" fill="#475569">不可达 —— Service / worker 拉不到投影</text>
<line x1="890" y1="195" x2="932" y2="195" class="flow" marker-end="url(#arrow)"/>
<rect x="40" y="290" width="1400" height="86" rx="10" fill="#fff7ed" stroke="#d97706" stroke-width="1.5"/>
<text x="56" y="312" class="h2" fill="#b45309">漂移从哪来(四类)</text>
<rect x="56" y="322" width="336" height="44" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="66" y="342" class="xs" font-weight="600">Service 重启</text>
<text x="66" y="358" class="xxs mut">Redis 未持久化丢配置、回落缺省</text>
<rect x="402" y="322" width="336" height="44" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="412" y="342" class="xs" font-weight="600">绕过治理直改</text>
<text x="412" y="358" class="xxs mut">有人直接改了 Redis / Nacos</text>
<rect x="748" y="322" width="336" height="44" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="758" y="342" class="xs" font-weight="600">激活部分失败</text>
<text x="758" y="358" class="xxs mut">某次激活没补偿干净、留半生效</text>
<rect x="1094" y="322" width="336" height="44" rx="8" fill="#ffffff" stroke="#d97706" stroke-width="1.3"/>
<text x="1104" y="342" class="xs" font-weight="600">机器遗留 env</text>
<text x="1104" y="358" class="xxs mut">env 压过了本该生效的激活值</text>
<text x="40" y="414" class="h2">篡改 → 检出 → 一键重推 → 收敛(闭环)</text>
<rect x="40" y="426" width="310" height="56" rx="8" fill="#fee2e2" stroke="#dc2626" stroke-width="1.6"/>
<text x="195.0" y="448" class="lbl" text-anchor="middle">篡改 / 漂移发生</text>
<text x="195.0" y="468" class="xxs mut" text-anchor="middle">绕过治理或 env 覆盖</text>
<rect x="402" y="426" width="310" height="56" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.6"/>
<text x="557.0" y="448" class="lbl" text-anchor="middle">对账检出 DRIFT</text>
<text x="557.0" y="468" class="xxs mut" text-anchor="middle">逐项列出差异旋钮</text>
<rect x="764" y="426" width="310" height="56" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="1.6"/>
<text x="919.0" y="448" class="lbl" text-anchor="middle">一键重推</text>
<text x="919.0" y="468" class="xxs mut" text-anchor="middle">重放激活把投影拉回激活版</text>
<rect x="1126" y="426" width="310" height="56" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="1.6"/>
<text x="1281.0" y="448" class="lbl" text-anchor="middle">收敛回激活版</text>
<text x="1281.0" y="468" class="xxs mut" text-anchor="middle">投影 = 权威、IN_SYNC</text>
<line x1="350" y1="454" x2="400" y2="454" class="flow" marker-end="url(#arrowR)"/>
<line x1="712" y1="454" x2="762" y2="454" class="flow" marker-end="url(#arrow)"/>
<line x1="1074" y1="454" x2="1124" y2="454" class="flow" marker-end="url(#arrowG)"/>
<rect x="40" y="512" width="690" height="96" rx="9" fill="#f1f5f9" stroke="#475569" stroke-width="1.4"/>
<text x="56" y="534" class="lbl">对账在防线里的位置</text>
<text x="56" y="554" class="xs mut">对账是「配置中心为权威、Service 与 worker 为投影」这个定位</text>
<text x="56" y="570" class="xs mut">的兜底闸,但不是失败的第一道防线 —— 第一道是激活失败时</text>
<text x="56" y="586" class="xs mut">的即时补偿(见图 2);对账兜的是补偿没覆盖到的漂移。</text>
<text x="56" y="602" class="xxs mut">一键重推 = 重放激活,幂等,可反复执行到收敛。</text>
<rect x="750" y="512" width="690" height="96" rx="9" fill="#faf5ff" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="6 4"/>
<text x="766" y="534" class="lbl" fill="#6b21a8">当前盲区(诚实标 · 阶段四补)</text>
<text x="766" y="554" class="xs mut">机器上遗留 env 覆盖压过激活值这类漂移,从 game-cloud 侧</text>
<text x="766" y="570" class="xs mut">看不见(env 只活在 worker 进程内),当前对账探不到。</text>
<text x="766" y="586" class="xs" font-weight="600" fill="#6b21a8">→ 挂阶段四观测:worker 暴露一个 effective 配置端点,</text>
<text x="766" y="602" class="xs" font-weight="600" fill="#6b21a8">把真正生效值连同来源吐出来供对账。</text>
<text x="40" y="640" class="h2">图例:</text>
<rect x="100" y="626" width="30" height="18" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
<text x="138" y="640" class="xs">IN_SYNC / 收敛</text>
<rect x="320" y="626" width="30" height="18" rx="8" fill="#fee2e2" stroke="#dc2626" stroke-width="1.5"/>
<text x="358" y="640" class="xs">DRIFT / 篡改</text>
<rect x="540" y="626" width="30" height="18" rx="8" fill="#e2e8f0" stroke="#64748b" stroke-width="1.5"/>
<text x="578" y="640" class="xs">不可达</text>
<rect x="720" y="626" width="30" height="18" rx="8" fill="#faf5ff" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="6 4"/>
<text x="758" y="640" class="xs">阶段四观测补(盲区)</text>
<rect x="1010" y="625" width="60" height="18" rx="3" fill="#0ea5e9"/>
<text x="1040.0" y="638" class="badge" text-anchor="middle" fill="#fff">可观测</text>
<rect x="1078" y="625" width="52" height="18" rx="3" fill="#16a34a"/>
<text x="1104.0" y="638" class="badge" text-anchor="middle" fill="#fff">可靠</text>
<text x="1140" y="640" class="xs mut">对账 = 可观测 · 一键重推 = 可靠</text>
<text x="40" y="680" class="mut xs">读这张图抓三点:① 权威是当前激活版、Service 与 worker 只是它的投影,对账拉投影比对权威、判三态;</text>
<text x="40" y="698" class="mut xs">② Nacos publish→read 最终一致,对账读必须带 8s 容忍窗,别把传播延迟误判成漂移;③ env 覆盖的漂移当前探不到,是诚实标的盲区,由阶段四 worker effective 端点补齐。</text>
<text x="40" y="740" class="mut xs">映射:本档 §3.6 配置漂移检测 · §8 执行终局③ · tech-decisions §14③ | 状态:现(a8dd5e50 · 8s 窗)+ 建(阶段四 env 覆盖对账)| 设计变动须同步本图</text>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB