From f9ee56e16ea18789c3b9906175c2500b540a4a7c Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 17 九月 2026 13:19:19 +0800
Subject: [PATCH] docs(agents): 按开发库改用共享库更正环境事实

---
 talent-card-server/README.md                          |   12 ++++--
 talent-card-server/src/main/resources/application.yml |    5 +-
 .scratch/db-merge/README.md                           |    5 ++
 docs/agents/testing.md                                |   48 ++++++++++++++++++++---
 AGENTS.md                                             |    9 +++-
 5 files changed, 63 insertions(+), 16 deletions(-)

diff --git a/.scratch/db-merge/README.md b/.scratch/db-merge/README.md
index 340aa3b..e9bb510 100644
--- a/.scratch/db-merge/README.md
+++ b/.scratch/db-merge/README.md
@@ -3,6 +3,11 @@
 本目录记录 2026-09-16 把**本机开发库**与**服务器库**并到一起的过程,以及可复现的工具与判定规则。
 目录里的探针都是一次性只读/迁移工具,不是业务代码。
 
+**2026-09-17 现状**:合并已完成,开发库从此就是那个共享库(`192.168.110.13:3306/talent_card`,MySQL 5.7.44);
+本机 `127.0.0.1:8134/talent_card` 只是合并前的副本,**不再作为开发库**使用(当前环境一览见
+`docs/agents/testing.md`)。本目录的工具只在需要重新比对或补 DDL 时才用,跑之前把 URL 换成当前开发库——
+`.scratch/` 下更早留下的一次性探针同理,它们默认写的就是那份旧副本。
+
 ## 当时的事实
 
 | | 服务器库 `192.168.110.13:3306/talent_card` | 本机开发库 `127.0.0.1:8134/talent_card` |
diff --git a/AGENTS.md b/AGENTS.md
index ba3ac6b..fafe8f2 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -20,7 +20,9 @@
 - **只改用户本次指派范围内的代码、迁移和前端。** 范围以用户的说明为准;用户没说清、或任务看起来横跨
   多个业务域时,先问,不要自己扩大范围。
 - **范围外的业务只做只读排查**:可以读代码、查库、跑 SQL、给出结论和建议,但不要直接改它的代码、
-  迁移和前端。各业务域的代码位置见 `CONTEXT.md`。
+  迁移和前端。域划分大致是:**支付链路**=汇付/斗拱进件与开通、支付、核销后的资金确认、自动结算与
+  结算记录、退款;**其余业务**=家属卡、洗车、停车、票券包、权益规则、资讯、各类申请审核等。
+  (根目录 `CONTEXT.md` 是**术语表**,里面没有代码位置。)
 - 需要修范围外的缺陷时,把「现象 + 根因 + 证据 + 建议改法」整理成 Markdown(放
   `.scratch/<feature-slug>/issues/`)交给用户转给该业务的负责人,不要直接动手。
 - **迁移编号是全仓共享的**:新增迁移前先看 `talent-card-server/src/main/resources/db/migration/` 里当前
@@ -34,8 +36,9 @@
 
 后端测试跑在共享的 MySQL 测试库上。跑测试用 `talent-card-server/scripts/run-server-tests.ps1`,
 重置库用 `talent-card-server/scripts/reset-test-db.ps1`,并遵守:已执行的迁移只追加不修改、同一
-checkout 一次只跑一个 Maven 构建、不要 `drop database`。详见 `docs/agents/testing.md`(含 3 项已知
-基线失败,不要为证明它们"是既有的"而重复造 worktree)。
+checkout 一次只跑一个 Maven 构建、不要 `drop database`。详见 `docs/agents/testing.md`(**开发库与
+测试库是哪两个库、什么版本**、3 项已知基线失败,以及一类会随测试库累积而出现的环境相关失败;不要为
+证明它们是"既有的"而重复造 worktree)。
 
 ### Git 提交
 
diff --git a/docs/agents/testing.md b/docs/agents/testing.md
index 56f2571..59445d4 100644
--- a/docs/agents/testing.md
+++ b/docs/agents/testing.md
@@ -3,6 +3,23 @@
 本文件是 `talent-card-server` 的测试约定。目标是让**新会话**不需要重新摸索环境:一条命令跑测试,
 一条命令重置库,并且不重蹈已知的坑。
 
+## 环境一览(2026-09-17 实测)
+
+| | 库 | 版本 | Flyway | 谁在连 |
+| --- | --- | --- | --- | --- |
+| **开发库** | `192.168.110.13:3306/talent_card`(局域网共享) | MySQL **5.7.44** | **关**(`flyway.enabled=false`) | 后端、后台管理页、两个小程序 |
+| **测试库** | `127.0.0.1:8134/talent_card_test`(本机实例) | MySQL **8.0.36** | **开** | 本文件的测试脚本 |
+
+三条由此推出的硬约束:
+
+- **迁移必须同时兼容 5.7 与 8.0**:测试只在 8.0 上跑,跑绿不代表开发库能执行(`V148` 的存储过程写法
+  已在 5.7 上实跑验证过,但每次新增迁移都值得照做一遍)。
+- **开发库的结构不由 Flyway 维护**:缺表缺列只能靠启动时的初始化器 best-effort 补,补不上就手工补(见下)。
+- 本机 `8134` 实例上另有 `talent_card`、`talent_card_dryrun`、`talent_card_verify1` 三个库:它们是
+  2026-09-16 把本机库并入服务器库**之前**的本机副本,**不再是开发库**,不要拿它们判断开发库状态。
+  早先会话留在 `.scratch/` 下的一次性探针(`*Probe*.java`、`Inspect*.java`、`Apply*.java` 等)大多把 URL
+  写死成 `127.0.0.1:8134/talent_card`,指的就是这份旧副本;复用时要显式传开发库 URL,别照默认值跑。
+
 ## 一条命令跑测试
 
 ```powershell
@@ -38,19 +55,24 @@
 
 ## 不要重建开发库
 
-`127.0.0.1:8134/talent_card` 是**开发库**(后台管理页和两个小程序都连它),不是测试库。它里面有
+开发库是局域网共享的那一个(`192.168.110.13:3306/talent_card`,见上表),不是测试库。它里面有
 一批**迁移从未创建**的表——当年是直接在库里手建的,例如 `dependent_card_apply`、`merchant_benefit_rule`。
 所以「把测试库结构克隆到开发库」「`reset-test-db.ps1 -Database talent_card`」这类操作会把开发库里这些
-表连同数据一起删掉:2026-09-13 就这样丢过一批,最后靠 `127.0.0.1:6134/talent_card` 上的同源快照才回灌回来。
+表连同数据一起删掉:2026-09-13 就这样丢过一批,最后靠一份同源快照才回灌回来(`reset-test-db.ps1`
+对名为 `talent_card` 的库一律拒绝,正是为此)。
 
-注意开发库的 `spring.flyway.enabled=false`:它**不会**被迁移自动修正,缺表只能手工补。
+注意开发库的 `spring.flyway.enabled=false`:它**不会**被迁移自动修正,缺表缺列只能手工补。
 
 需要让开发库结构跟上迁移时:
 
-- 只补缺失的 DDL(`create table if not exists`),**不要**删表重建;
-- 动结构之前先 dump:`docker exec talent-card-mysql-1 mysqldump -uroot -p123456 talent_card > backup.sql`;
-- 从旧快照回灌数据用 `.scratch/automatic-withdrawal/tools/RestoreOldData.java`(按列交集 `INSERT IGNORE`,
-  只新增不删改)。该 MySQL 开了 binlog 且保留 30 天,误删后还能查证与补救。
+- 只补缺失的 DDL(`create table if not exists`、`add column`),**不要**删表重建。手工补 DDL 正是
+  2026-09-17「点开收款能力就 500 / `Unknown column 'capability_sync_until'`」的解药。
+- 动结构之前先备份。本机**没有** mysql 客户端、也没有 Docker(README 里指向 `D:\MySQL\...` 和
+  `docker exec talent-card-mysql-1` 的两条老做法都已失效),要备份就在 DB 主机上做,或照
+  `scripts/reset-test-db.ps1` 的办法用项目已有的 JDBC 驱动写个单文件程序。
+- 初始化器是 **best-effort** 的:它的 `alter table` 等 DDL 元数据锁的上限只有 5 秒,等不到就记一条
+  error 放行(宁可少一列,也不能让启动被 DDL 挂住——2026-09-15 为此瘫过一次)。所以「重启过就一定有
+  新列」不成立:启动日志里搜 `Merchant onboarding schema: could not add`,那里会给出可直接执行的手工补救语句。
 
 ## 迁移是只追加的
 
@@ -70,6 +92,18 @@
 
 新会话不要为了证明它们"是既有的"而重建 worktree:直接看这张表。修好其中任何一项时,请删掉对应行。
 
+## 环境相关失败(不是基线,别当既有失败放过)
+
+`PaymentFundConfirmationTests.aPendingConfirmationOfAVerifiedOrderIsRetriedWithoutAnotherVerification`
+在测试库累计的「已核销 + 待确认」订单超过 50 条时会**必然**失败:补偿任务扫全库、`order by o.id asc
+limit 50`(`PaymentFundConfirmationRetry.retry`),而用例新建的那单 id 最大、排在窗口之外,于是状态停在
+`pending`。这是测试库长期不清理累积出来的,不是代码回归——2026-09-17 实测符合条件的行为 60 条,最早一条
+09-14 就留下了,而且被处理过的行多数停在 `confirming`(仍在扫描条件内),所以不会自己排空。
+
+现象、证据与建议改法见
+[.scratch/payment-fund-confirmation-retry/issues/01](../../.scratch/payment-fund-confirmation-retry/issues/01-retry-limit-blocked-by-accumulated-leftovers.md)
+(属支付链路范围,本轮只排查未修)。要么让用例自己把窗口腾出来,要么清理测试库遗留(后者只能缓解)。
+
 ## 测试库的状态是共享的
 
 Spring 测试共用一个 schema,测试之间不做清理(没有 `@Transactional` 回滚)。因此:
diff --git a/talent-card-server/README.md b/talent-card-server/README.md
index 1944f51..546ec59 100644
--- a/talent-card-server/README.md
+++ b/talent-card-server/README.md
@@ -15,12 +15,15 @@
 
 ## 本地启动
 
-当前默认适配本机 MySQL 5.7:`localhost:3306`,数据库名 `talent_card`,账号 `root`,密码 `123456`。
+默认连**共享开发库**:`192.168.110.13:3306/talent_card`(MySQL 5.7,`root`/`123456`,
+`flyway.enabled=false`)。本机不需要再起 MySQL。
 
-先在本机 MySQL 执行初始化脚本:
+下面的初始化脚本与 `D:\MySQL\MySQL Server 5.7\...` 那套做法是**并入共享库之前的历史**,只在自己搭一套
+全新的库时才需要(本机那份 mysql 客户端已不存在)。库的归属与版本以
+[`docs/agents/testing.md`](../docs/agents/testing.md) 的「环境一览」为准。
 
 ```powershell
-& "D:\MySQL\MySQL Server 5.7\bin\mysql.exe" -uroot -p < scripts\init-local-mysql.sql
+& "<本机 mysql 客户端>\bin\mysql.exe" -uroot -p < scripts\init-local-mysql.sql
 ```
 
 ```bash
@@ -53,6 +56,7 @@
 ```
 
 该脚本仅用于已中断 V9 的旧本机数据库;它保留历史电影票记录,并让 Flyway 重新执行 V9 及后续迁移。新建数据库不需要执行。
+(命令里的本机客户端路径已失效,换成任意可用的 mysql 客户端即可;共享开发库不涉及这套修复。)
 
 如果临时想用 Docker MySQL,compose 已经避开本机 3306,映射为 `localhost:3307`:
 
@@ -87,7 +91,7 @@
 | 变量 | 默认值 |
 | --- | --- |
 | `SERVER_PORT` | `8080` |
-| `MYSQL_URL` | `jdbc:mysql://localhost:3306/talent_card...` |
+| `MYSQL_URL` | `jdbc:mysql://192.168.110.13:3306/talent_card...`(共享开发库;可用环境变量覆盖) |
 | `MYSQL_USERNAME` | `root` |
 | `MYSQL_PASSWORD` | `123456` |
 | `REDIS_HOST` | `localhost` |
diff --git a/talent-card-server/src/main/resources/application.yml b/talent-card-server/src/main/resources/application.yml
index a514336..e934517 100644
--- a/talent-card-server/src/main/resources/application.yml
+++ b/talent-card-server/src/main/resources/application.yml
@@ -9,8 +9,9 @@
       max-file-size: 10MB
       max-request-size: 10MB
   datasource:
-    ## 本地开发:用 MYSQL_URL 覆盖成本机库(例如 jdbc:mysql://127.0.0.1:8134/talent_card)。
-    ## url: ${MYSQL_URL:jdbc:mysql://127.0.0.1:8134/talent_card?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false}
+    ## 默认连共享开发库(局域网 192.168.110.13,MySQL 5.7,flyway 关闭)。
+    ## 要连别的库时用 MYSQL_URL 覆盖,例如本机 8134 上的那份副本:
+    ##   jdbc:mysql://127.0.0.1:8134/talent_card?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
     url: ${MYSQL_URL:jdbc:mysql://192.168.110.13:3306/talent_card?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false}
     username: ${MYSQL_USERNAME:root}
     password: ${MYSQL_PASSWORD:123456}

--
Gitblit v1.7.1