diff --git a/docs/SKILL-INDEX.md b/docs/SKILL-INDEX.md
index ad5a152..87aee16 100644
--- a/docs/SKILL-INDEX.md
+++ b/docs/SKILL-INDEX.md
@@ -31,7 +31,7 @@
引擎特定的现场材料按引擎分组,每个引擎一个子目录:
-- [`cases/mariadb/`](cases/mariadb/) — 15 个 mariadb addon 案例
+- [`cases/mariadb/`](cases/mariadb/) — 16 个 mariadb addon 案例
- [`cases/valkey/`](cases/valkey/) — 2 个 valkey 案例
- [`cases/oracle/`](cases/oracle/) — 7 个 oracle 案例
- [`cases/oceanbase/`](cases/oceanbase/) — 3 个 oceanbase 案例
diff --git a/docs/cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md b/docs/cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md
new file mode 100644
index 0000000..808d7a4
--- /dev/null
+++ b/docs/cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md
@@ -0,0 +1,80 @@
+# MariaDB reconfigure SET GLOBAL × ConfigMap sync race 案例
+
+> **Audience**: addon dev / test 在 reconfigure / Reconfiguring OpsRequest 场景,特别是涉及 SET GLOBAL + restart-prone 拓扑
+> **Status**: stable (root cause closed, alpha.84 chart fix landed)
+> **Applies to**: MariaDB addon semisync 拓扑
+> **Applies to KB version**: KB 1.2.0-alpha.1(+ 5 fixes + V(1) 诊断 + kbagent pullPolicy fix)
+> **Affected by version skew**: no — 由 addon 自身写法决定,跨 KB 版本一致
+
+通用方法论见 [`../../troubleshoot/addon-reconfigure-set-global-persist-race-guide.md`](../../troubleshoot/addon-reconfigure-set-global-persist-race-guide.md);本案例只保留 MariaDB-specific 现场材料。
+
+## MariaDB 特有的根因链
+
+1. semisync 拓扑没有声明自己的 `ParametersDefinition`(chart 漏写)→ KB Configure controller 不知道 `slow_query_log` / `long_query_time` 是 dynamic → 默认走 rolling restart 路径
+2. rolling restart 在 semisync 拓扑里表现成 switchover / promote → 新主 mariadbd 进程级 restart
+3. chart 的 `reconfigureAction` 只跑 `SET GLOBAL`(运行时生效),不落任何持久化文件
+4. mariadbd restart 时机点上 `/etc/mysql/conf.d/my.cnf` 还没收到 kubelet 的 ConfigMap volume 同步(典型几秒到约 60s 延迟)→ mariadbd 读旧 my.cnf → 加载 chart 默认值
+5. SET GLOBAL 应用的运行时状态被 restart 抹掉,最终运行时 = chart 默认
+
+## 现场证据(alpha.83 clean R1)
+
+| 字段 | pod0(原 primary → 当前 secondary) | pod1(原 secondary → 当前 primary) |
+|---|---|---|
+| OpsRequest phase | Succeed | Succeed |
+| ComponentParameter | Finished, succeedCount=2 / expectedCount=2, revision=4 | 同 |
+| kbagent action stdout | reconfigure success | reconfigure success @ 20:42:11 |
+| K8s container restartCount | 0 | 0 |
+| K8s container startedAt | 未变 | 未变 |
+| mariadbd PID | 未变 | **20:42:33 新 PID**(进程级 restart) |
+| mariadb error log shutdown | 无 | `Normal shutdown` 20:42:29 |
+| /etc/mysql/conf.d/my.cnf 内容 | slow_query_log=ON | slow_query_log=ON(**但更新时间晚于 mariadbd restart**) |
+| `SHOW GLOBAL VARIABLES slow_query_log` | ON ✓ | **OFF** ✗ |
+| `SHOW GLOBAL VARIABLES long_query_time` | 3 ✓ | **10** ✗ |
+
+## 时间线(pod1 的窗口)
+
+```
+T+0 reconfigure action runs SET GLOBAL slow_query_log=ON on both pods
+T+10s ConfigMap update commits to etcd
+T+15s KB triggers switchover/promote (PD 缺失 → 默认 rolling restart 路径)
+T+15s pod1 mariadbd receives SIGTERM, normal shutdown
+T+18s pod1 mariadbd new process starts
+ reads /etc/mysql/conf.d/my.cnf — STILL OLD (kubelet not synced yet)
+ loads slow_query_log=OFF (chart default)
+T+45s kubelet ConfigMap volume sync completes
+ /etc/mysql/conf.d/my.cnf now has slow_query_log=ON
+ but mariadbd is already in-memory running with OFF
+T+60s test checks SHOW GLOBAL VARIABLES → OFF ✗
+```
+
+## 修法(alpha.84,4 处 chart 改动)
+
+1. 补 `mariadb-semisync-pd` 到 `paramsdef.yaml` — `componentDef: ^mariadb-semisync-`、`templateName: mariadb-semisync-config`、dynamic/static 复用同一份 `mariadb-config-effect-scope.yaml`
+2. `mariadb-semisync.tpl` 末尾追加 `!includedir /var/lib/mysql/runtime-overrides.d/`
+3. `cmpd-semisync.yaml` init-syncer 加 `mkdir -p {{ .Values.dataMountPath }}/runtime-overrides.d`
+4. `mariadb.config.reconfigureAction` helper:SET GLOBAL 成功后写 `${OVERRIDES_DIR}/.cnf`(per-param file,temp + atomic rename,写入失败 WARN-only 不 fail action)
+
+L1 修法(补 PD)让常规路径不再 restart;L2 修法(持久化)兜底 OOMKill / 节点驱逐 / 手动维护等不可控 restart 路径。两层都做才闭环。
+
+## 边界
+
+- 适用拓扑:semisync(有 promote/switchover 路径 + SET GLOBAL reconfigureAction)
+- replication / standalone 拓扑也写了 SET GLOBAL reconfigureAction,但 restart 路径较少;如果用户手动 `kill -TERM mariadbd` 也会丢值;建议同样落 L2 持久化(已含在 alpha.84 chart helper 修法里)
+- alpha.85 / alpha.88 后续版本是同一修法路径的 chart-immutability 迭代,本质上不变
+
+## 现场证据归档
+
+- 失败样本 evidence tar sha:`9502a88ff4a89c17af87649f83c9662bab1b51a699c77e3541a3dd53115fec67`
+- summary md sha:`4fa0f12f602bf5f3d19377987f83f1a27e92f9d4bdf0588bf99e32422f8e2af2`
+- 修法 chart 版本:MariaDB addon `1.1.1-alpha.84+`(实际 land 版本含 alpha.85 + alpha.88 修复层)
+
+## 相关文档
+
+- 通用方法论:[`../../troubleshoot/addon-reconfigure-set-global-persist-race-guide.md`](../../troubleshoot/addon-reconfigure-set-global-persist-race-guide.md)
+- 同主题 MariaDB 案例:[`cm1-dynamic-reload-case.md`](cm1-dynamic-reload-case.md)(reloadAction 未落 live PD)+ [`cm4-bounded-window-helper-semantic-bug-case.md`](cm4-bounded-window-helper-semantic-bug-case.md)(CM4 bounded window)
+- 设计入口:[`../../design/addon-reconfigure-guide.md`](../../design/addon-reconfigure-guide.md)
+- evidence-discipline:[`../../test/addon-evidence-discipline-guide.md`](../../test/addon-evidence-discipline-guide.md)
+
+## 一句话总结
+
+MariaDB semisync 这次不是 OpsRequest 计数错,而是 `SET GLOBAL` 未持久化撞上进程级 restart;PD + PVC override 两层修法一起落才闭合。
diff --git a/docs/troubleshoot/README.md b/docs/troubleshoot/README.md
index cf65203..d468ce3 100644
--- a/docs/troubleshoot/README.md
+++ b/docs/troubleshoot/README.md
@@ -18,3 +18,4 @@
- [`addon-image-tag-vs-pr-merge-boundary-guide.md`](addon-image-tag-vs-pr-merge-boundary-guide.md) — release image tag 不等于 "截止 release 时间所有已合并 PR" 集合;三步 verification + 7 类陷阱
- [`addon-mariadb-grant-monitor-priv-mariadb-11-4-guide.md`](addon-mariadb-grant-monitor-priv-mariadb-11-4-guide.md) — MariaDB 11.4+ 上 `REPLICATION CLIENT` 不再覆盖 `SLAVE MONITOR`;`SHOW SLAVE STATUS` 失败时按 `SHOW GRANTS` 定位并补显式授权
- [`addon-instanceset-image-tag-alias-readiness-trap-guide.md`](addon-instanceset-image-tag-alias-readiness-trap-guide.md) — sideload 后 pod 已 Ready 但 InstanceSet 仍 NotReady 这一具体表现的诊断 + 多节点收口;同 digest 多 tag 的成因和通用修法(删 base alias / chart digest pin)参考 [`../agent-collab/addon-patch-image-build-handoff-roles-guide.md`](../agent-collab/addon-patch-image-build-handoff-roles-guide.md) 的 "Sideload + tag 别名陷阱" 一节
+- [`addon-reconfigure-set-global-persist-race-guide.md`](addon-reconfigure-set-global-persist-race-guide.md) — reconfigureAction 只跑 `SET GLOBAL` / `CONFIG SET` 等运行时语句不落持久化文件时,遇到引擎进程级 restart(switchover promote / OOMKill / 节点驱逐 / KB 默认 rolling restart)会让 OpsRequest phase=Succeed 但运行时回 chart 默认;防御两层:补 ParametersDefinition + reconfigureAction 同步写 PVC 持久化 override
diff --git a/docs/troubleshoot/addon-reconfigure-set-global-persist-race-guide.md b/docs/troubleshoot/addon-reconfigure-set-global-persist-race-guide.md
new file mode 100644
index 0000000..d6aa00d
--- /dev/null
+++ b/docs/troubleshoot/addon-reconfigure-set-global-persist-race-guide.md
@@ -0,0 +1,150 @@
+# reconfigure 只跑 runtime apply 不持久化 × restart race
+
+> **Audience**: 任何写 addon `reconfigureAction` 的人;常用引擎 `SET GLOBAL` / `CONFIG SET` / `ALTER SYSTEM` / `redis-cli CONFIG SET` 等"运行时生效"语句
+> **Status**: stable methodology
+> **Applies to**: 任何 addon 的 `reconfigureAction` / `reloadAction` 只用引擎 runtime-apply 语句改参数、不在动作里持久化到引擎重启可读路径的场景
+> **Applies to KB version**: KB 1.0+,与 KB 控制器版本无关;触发条件是 addon `reconfigureAction` 写法本身
+> **Affected by version skew**: no — addon `reconfigureAction` 写法决定,跨 KB 版本一致
+> **Engine-neutral**:引擎相关现场材料见各 case,如 [`../cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md`](../cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md)
+
+## 问题
+
+OpsRequest Reconfigure 报 `phase=Succeed`,但被改的参数在引擎一次进程级 restart 之后悄悄回到 chart 默认值。这一类 false-success 出现的根因是:`reconfigureAction` 只用引擎的"运行时生效"语句把变更打到 in-memory state,并没有把变更落到引擎下一次启动时还能读到的持久化路径;任何 restart 路径(switchover / OOMKill / 节点驱逐 / KB 默认 rolling restart / 引擎自身 reload)都会把 in-memory state 抹掉,回到 chart 默认。
+
+## 先用白话理解这篇文档
+
+OpsRequest Reconfigure 报 `phase=Succeed` 不等于 invariant 持续。如果你的 `reconfigureAction` 只用引擎的"运行时生效"语句改参数(`SET GLOBAL` / `CONFIG SET` 等),但没把变更落到引擎重启后还能读到的文件里,那么遇到下面任何一个 restart 路径都会丢值:
+
+- 用户触发 switchover → 新主 promote 路径里可能重启引擎进程
+- 节点 OOMKill → kubelet 重建 container 或拉起新进程
+- 节点驱逐 / 维护
+- KB 自己因不知道这个参数是 dynamic 还是 static 而默认走 rolling restart
+- 引擎自身的 SIGHUP / 重载策略
+
+这篇 guide 给你一个统一的修法框架,让你的 reconfigureAction 通用地避开这一类 race。
+
+## 触发条件
+
+三件事同时成立才出问题:
+
+1. `reconfigureAction` 用引擎的"运行时生效"语句改参数,不落任何持久化文件
+2. 引擎进程在 reconfigure 窗口里发生 restart(任何路径)
+3. 引擎 restart 时还没读到包含新值的 config 文件(典型 ConfigMap-as-volume kubelet sync 延迟)
+
+## 症状("长这样的 false-success")
+
+复合特征同时出现就大概率是这一类:
+
+- OpsRequest `phase=Succeed`
+- ComponentParameter `phase=Finished`、`currentRevision == updateRevision`、`expectedCount == succeedCount`
+- addon action attestation 所有 pod 都报 success
+- 但业务层 `SHOW VARIABLES` / `CONFIG GET` / `SHOW LIKE` 至少一个 pod 还是 chart 默认值
+- K8s container `restartCount=0`,`containerStatuses[].state.startedAt` 没变 ← **这条非常容易误导**
+
+## 反例(不要这样判断)
+
+| 误判 | 反例为什么不成立 |
+|---|---|
+| "runner 抢答 / 测试时机不对" | bounded wait 后再次查仍是旧值 |
+| "kbagent 没在所有 pod 都跑 action" | attestation 显式覆盖所有 pod 都 success |
+| "controller succeedCount 算错" | 现场 pod kbagent action stdout 本来就 success;不是计数虚报 |
+| "trap #4 image alias 还没清干净" | image identity 已 verify |
+| "K8s container restartCount=0,所以没重启" | **容器没重启不等于引擎进程没重启**;进程级 restart 在容器视角是透明的 |
+
+## 区分这一类的关键证据
+
+不能停在 k8s 层。必须进入 container 看进程层:
+
+1. **引擎 error log 的 shutdown / startup 序列**:reconfigure 窗口附近有没有 `shutdown` / `starting` / `ready` 序列?
+2. **引擎主进程 PID 是否变化**:`ps -e | grep ` 在 reconfigure 前后是否同一个 PID?
+3. **ConfigMap-mounted my.cnf / redis.conf 等的内容 vs mtime**:reconfigure 之后该文件内容是否反映新值?mtime 是什么时候?
+4. **比较 config 文件更新时间 vs engine restart 时间**:如果 engine restart 在 config 文件更新之前,就是这一类 race
+5. **switchover / role 变化**:reconfigure 窗口里有没有 promote/demote 事件?哪个 pod 变化了?
+
+如果这五条满足"engine 进程重启过 + config 文件落后于 engine restart" → race 成立。
+
+## 修法(两个防御层都要做)
+
+### 防御层 L1:声明清楚 dynamic / static,避免 unnecessary restart
+
+- 给每个 topology / cmpd 写自己的 `ParametersDefinition`,不要共用一份不匹配的
+- `componentDef` 字段(regex 或精确)要真匹配你的 cmpd 名字
+- `templateName` 要匹配 cmpd 里 `configs[].name`,**不是** ConfigMap object 名(这是常见错位 — Galera 案例已经有这个 trap)
+- `staticParameters` / `dynamicParameters` 列表完整覆盖你支持的参数
+
+正确声明后,KB Configure controller 看到 dynamic 参数变更时不会触发 rolling restart,避免大多数 restart 路径。
+
+### 防御层 L2:持久化 reconfigure 值
+
+即使 PD 完美声明,仍有不可控的 restart 路径(OOMKill / 节点驱逐 / 手动维护)。reconfigureAction 必须把新值同时写到引擎重启后能读到的持久化路径。
+
+通用模式:
+
+```sh
+# 1. 引擎运行时生效(必做)
+engine_cli "SET GLOBAL = "
+
+# 2. 持久化(必做,写到 PVC 等不依赖 ConfigMap sync 的路径)
+OVERRIDES_DIR="/var/lib//runtime-overrides.d"
+mkdir -p "$OVERRIDES_DIR"
+override_tmp="$OVERRIDES_DIR/.cnf.tmp.$$"
+{
+ echo "# Written by reconfigureAction on $(date -u +%Y-%m-%dT%H:%M:%SZ)"
+ echo "[]"
+ echo " = "
+} > "$override_tmp" && mv "$override_tmp" "$OVERRIDES_DIR/.cnf"
+```
+
+关键点:
+
+- **per-param 文件**,独立 reconfigure op 不互相覆盖
+- **temp + atomic rename**,被中断不会留半文件让 engine 启动失败
+- **WARN-only 失败模式**:写文件失败不让 action fail(SET GLOBAL 已成功,运行时已生效;持久化是 defense-in-depth)
+- **写到 PVC 等持久化卷**,不要写到 ConfigMap 挂载的只读路径(写不进去),也不要写到 emptyDir(pod 重建丢失)
+
+### 让 engine 读到持久化文件
+
+写完文件后还要让 engine 启动时读到。两条路径:
+
+**A. 通过 main config 文件 include**:
+
+```ini
+# /etc//conf.d/main.cnf ← chart 的 ConfigMap 渲染
+[]
+... chart defaults ...
+!includedir /var/lib//runtime-overrides.d/ # ← include 在末尾,override 胜出
+```
+
+注意 `!includedir` 的语义:包含目录里所有 .cnf 文件,silently 跳过不存在的目录。chart bootstrap 创建空目录以保证 directive 永远 safe。
+
+**B. 通过 engine 启动参数 `--defaults-extra-file`**:
+
+如果引擎不支持 include 语法,可在 cmpd container args 加 `--defaults-extra-file=` 或等效。
+
+## 测试 verify gate(任何 reconfigure fix 都应该过这 4 项)
+
+1. **PD 命中**:`kubectl get parametersdef ` Available;`dynamicParameters` / `staticParameters` 包含目标参数
+2. **不触发 rolling restart**:reconfigure 前后所有 pod UID + startTime + restartCount + role label 完全一致
+3. **OpsRequest Succeed 后所有 pod runtime 立刻反映新值**:bounded wait 不超过 5s
+4. **强制 engine 进程 restart 后值仍保留**:手动 `kill -TERM` engine 进程,等被 kbagent / 容器 entrypoint 拉起,再次查 runtime 应该仍是新值(证明持久化文件被 engine 启动加载)
+
+**N≥3 fresh 集群** 4 项全过才算 axis closed。单次过不能写 release-ready。
+
+## 给跨 addon 团队的 4 条可复用经验
+
+1. **任何 runtime-apply 语句都要配持久化备份**。MariaDB `SET GLOBAL`、PostgreSQL `ALTER SYSTEM`(自带持久化但用法要对)、MySQL `SET PERSIST`(自带,对)、Valkey `CONFIG SET`(**不**自带,需要 `CONFIG REWRITE` 跟上)、Redis 同
+2. **PD 缺失会让 KB 默认 rolling restart**。每个 topology 上线时检查 PD componentDef regex 是否真的匹配 cmpd
+3. **K8s container restartCount=0 不代表引擎进程没重启**。诊断要进 container 看进程层
+4. **OpsRequest phase=Succeed 不等于业务 invariant 持续**。测试必须 bounded wait + 再次查询确认未回退
+
+## 相关文档
+
+- [`../cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md`](../cases/mariadb/mariadb-reconfigure-set-global-without-persist-race-case.md) — MariaDB 现场材料
+- [`../cases/mariadb/cm1-dynamic-reload-case.md`](../cases/mariadb/cm1-dynamic-reload-case.md) — reloadAction 未落 live PD 的同主题相关案例
+- [`../design/addon-reconfigure-guide.md`](../design/addon-reconfigure-guide.md) — reconfigure 设计入口
+- [`../test/addon-evidence-discipline-guide.md`](../test/addon-evidence-discipline-guide.md) — "phase Succeed ≠ invariant 持续" 是 evidence-discipline Rule A 的具体形状
+- [`../test/addon-bounded-eventual-convergence-guide.md`](../test/addon-bounded-eventual-convergence-guide.md) — bounded wait 而非 single-snapshot 验证
+
+## 一句话总结
+
+`reconfigureAction` 只改运行时状态不落持久化文件时,OpsRequest 成功也可能在一次引擎进程 restart 后回到 chart 默认;修法是声明正确 PD 并把 reconfigure 值写进引擎启动会读取的持久化路径。