# ws 联调进度与交接（截至 2026-07-30 午间）

> 给下一次接手的人（或下一个对话）用。三分钟读完就能接着干。
> 入口文档仍是 `README.md` / `POSITION_MGMT_DESIGN.md`（V0.4 定稿，勿改）/
> `QMT_WS_PROTOCOL.md`（V1.0 定稿）。本文只记**当前状态**和**踩过的坑**。

---

## 1. 一句话状态

**ws 通道全线打通并实测通过；S3 五类已凑齐（07-30 上午补完撤单/过期两类）；账本已于 07-30 11:14
清干净，PMS 与下游双方持仓皆空、等对端装持仓后认领；`PMS_DISPATCH_MODE` 仍是 `shadow`，一次
真实指令都没发过。卡在切换前的是两件事：对端 `trade_no` 不合 §5.5、19 条 `SIG_INVALID` 未查明。**

---

## 2. 已验证（实测，非推演）

| 项 | 依据 |
|---|---|
| Ed25519 双向签名 | 与对端 `crypto.py` 逐字比对 + 双向验签实测 |
| 握手 / 心跳 / 重连退避 | 一天累计近百次重连，seq 水位每次无缝续接 |
| `ack_seq` 累积确认（§4.5） | 对端补上实现后，PMS 不再降级停发 |
| **§6.1 序号补发** | `ws_smoke rewind --by 60` 人为造缺口，对端从 `last_seq+1` 起严格按序补回 60 条，约 15ms/条，一条不漏 |
| 委托全链路 | `place_order → ack → order_update(SUBMITTED) → trade → persist_result → order_update(FILLED) → funds_update`，状态推进与字段全对 |
| 入账分流 | 只有 `trade` 进账本（`processed=0`），其余一律「已消化」 |
| 页面 ws 监控页签 | 真浏览器实测（含告警渲染、pong 过滤、轮询起停） |

**07-30 上午补测（对端已上模拟环境的 R1/R2）**：

| 项 | 结果 | 实测依据 |
|---|---|---|
| R1 可控成交 | ✅ | `600000.SH sell 100 @10.13`（涨跌停带内、高于市价）停在 `SUBMITTED`、成交 0——同代码同数量的 `@99.99` 07-29 是秒成 |
| 主动撤单 `CANCELLED` | ✅ | seq 7089 `SUBMITTED` → 7106 `CANCELLED`；本地 `cancel_state=SENT` 与对端终态一致，无不一致告警 |
| 到期过期 `EXPIRED` | ✅ | `--ttl 1` → seq 7124 `SUBMITTED` → 7137 `EXPIRED` |
| R2 代码校验 | ✅ | `999999.SH` → `reject{instruction_id, code=UNKNOWN_CODE, reason="instrument not found"}`；码值是协议 §7.3 表里的，带 `instruction_id`（委托级而非协议级），三点全对 |
| 部分成交 `PARTIAL` | ✅ | 07-29 已产出：`INS-20260729-4ec5ce4c` 走 seq 6028 `PARTIAL` → 6035 `PARTIAL` → 6040 `FILLED` |
| 时钟与投递 | ✅ | `min +868 ms` = 真实时钟差约 0.87 秒，`max-min` 仅 74 ms——07-29 那个 +30213 ms 的事件循环卡顿没再出现，`ack_seq` 挪出控制面的改法生效了 |

**S3 五类至此各至少一次**（全成 / 部分成交 / 主动撤单 / 到期过期 / 拒绝）。
剩下的验收条件是**日终对账零差异**，以及下面 §5 的三件待办。

协议三条安全底座（签名、补发、对账兜底）前两条已齐——但签名那条被 §5 的 `SIG_INVALID` 划了个问号。

---

## 3. 当前状态与未决项

### 3.0 账本已清干净（07-30 11:14）——当前基线

`reset_ledger.py --yes --drop-reports` 执行完毕，删 816 行：
`pms_lot` 33 / `pms_position` 24 / `pms_instruction` 7 / `pms_action_ledger` 750 /
`pms_proposal` 1 / `pms_daily_report` 1（`pms_cash_flow`、`pms_plan`、`pms_command` 本来就是 0）。

**当前基线**（下一次开工从这里读起）：

| 项 | 状态 |
|---|---|
| PMS 账本 | 空。`/api/positions` 返回 `positions: []`，`cash_est` = 200 万 |
| 下游 `trading_position` | **QMT 侧已清空**（07-30 上午），那行 `999999.SH × 2000` 假数据没了 |
| 通道两表 | **有意保留**：`pms_qmt_order` 7 行 / `pms_qmt_inbox` 7881 行。留着是零风险（trade 行都是 `processed=1`，只有 0 才会被消费），换来上行审计与 trade_no 去重层都在，且出口表是 SMOKE_ 联调单的唯一判据 |
| ws seq 水位 | 8052，**未动**。与对端自报 8045 在握手那一刻是对齐的（收发差即会话内 pong 推进），无倒挂无缺口 |
| 回放游标 | 重新 seed 到 `SELL_688819.SH_1774588308`（字典序锚点，此后不追认历史） |
| `PMS_RECON_STREAK` | 归零 |
| `PMS_SIGNAL_ENABLED` | **False**（清账期间关的）。**账本重建完必须打开**，理由见 §7 |
| `pms-beat` | **停着**（07-30 12:xx 主动停的）。原因：账本空时爆炸半径闸放行，15:10 的 `daily_settle` 会**无条件**认领 `trading_position` / ws 快照里的东西，而那 1100 股来历待对端确认（§5.1）。`pms-web` / `pms-ws` 照常跑——页面能看，ws 继续拉快照 |
| `PMS_TOTAL_SCALE` | **98 万**（07-30 由 200 万改，与模拟账户 `total_asset 981448.56` 对齐）。实盘前按真实投入资金重设 |
| ws 持仓/资金快照 | ✅ 已通。`query_positions` / `query_funds` 每 300 秒一轮，对端字段完全按 §5.7。持仓 1 条：`600000.SH 1100 @ 9.2732`；资金：`total_asset 981448.56 / available_cash 971251.56 / sell_return_today 0` |
| 下游 `trading_buy_plan` 轮询 | **已于 2026-07-30 10:55 停止**——`QMT_INTERFACE_REQUIREMENTS.md` C2 那个「当前最大未决项」至此闭环 |

调度恢复后一轮四个调度位全部空转正常：`signal_digest` 报「已关闭」、`command_poll` 空、
`intraday_exec` `candidates: 0` / `mode: shadow`、`replay_fills` `fills 0` + `ws.trades 0` +
`light_recon {diffs: 0, severity: OK}`。

### 3.1 清账前是什么样（留档，问题已修）

07-29 那次事故（15:10 `daily_settle` 的 `reconcile()` 读到**下游持仓表空集**，按铁律
「以下游为准」把 22 个持仓、约 126 万市值全部核销）依然成立，机制也已由代码确认
（`reconcile` 无条件应用 fixes，且空结果集会跳过数量列校验）。但**清空之后账本又长出了东西**：

```
600000.SH  HOLDING  1100 股  avg_cost 9.273   ← 11 笔联调成交被判成「外部成交」并入 BASE
999999.SH  HOLDING  2000 股  avg_cost 9.274   ← 假代码, 防线部署前从下游对账补进来的
```

污染路径（07-30 查明，不是推测）：出口表 `pms_qmt_order` 现在只剩 7 行，而 inbox 里的
trade 引用了 `4ec5ce4c` / `f0efcf41` / `43e47c39` 三个**出口表里根本没有**的 instruction_id
（共 11 笔）。`consume_ws_trades` 原先沿用 `replay_fills` 的口径「反查不到就按真单走，宁可
多入账也不能漏账」，于是这 11 笔走了真单分支 → 指令也查不到 → 判为外部成交并入 BASE。
`SMOKE_` 那道闸**压根没机会生效**，因为它的判据正是「反查出口表」。

- 14 条 trade 现在全部 `processed=1`（已入账），不是「已消化」
- 根因是**上下游都停了但遗留数据没清**——停机遗留 ≠ 外部成交，这个缺口已在 §4 堵掉
- 处置：已按 §3.0 清账重来。那 22 只的批次结构不可逆地没了，接受损失

### 3.2 下游只有垃圾

`trading_position` 现在只剩 `999999.SH × 2000`——我们自己测拒绝路径用的假代码。
现已被代码合法性校验过滤，不会再流进账本。

### 3.3 7 张风控 EXIT 已撤销

`origin_type=system` / `origin_id=intraday` / `from_signal=true`，理由「风控 SELL 置信度
95% ≥ 85%, 清仓」。持仓归零后指令悬空，已全部 cancel。**不是用户下的命令。**

### 3.4 组合基线（事故前，供重建时参考）

22 只 · 市值 1,258,357 / 成本 1,515,139（−16.9%）· 62.9% vs 60% 上限 ·
22 家 vs 15 家上限 · 16 只 ≤ −15%。
`688825.SH` 成本 8.66 / 现价 48.5 是**新股中签**，数据正确，非异常。

---

## 4. 今天新加的防线（都有测试锁死）

| 防线 | 位置 | 起因 |
|---|---|---|
| 对账爆炸半径 | `ledger_service._recon_blast_guard` | 下游读空清了 22 个持仓 |
| 下游代码合法性 | `command_spec.is_stock_code` | `999999.SH` 差点被补进账本 |
| 联调单不入账 | `ledger_service.consume_ws_trades` + `qmt_repo.SMOKE_PREFIX` | 对端按限价全成，每张测试单都在赌账本 |
| 卖出认领不到时告警 | `recon.map_trades_to_book` | 买入告警而卖出静默核销，不对称 |
| 补发期告警限流 | `runner._persist_upstream` | 一次补发刷 60 行 WARNING，真乱序会被埋掉 |
| 时延采样跳过补发件 | `runner._track_skew` | 补发原样重放旧 ts，误报 345 秒卡顿 |
| **孤儿成交挂起不入账**（07-30） | `ledger_service.consume_ws_trades` + `qmt_repo.PROC_ORPHAN` | 11 笔停机遗留成交被判成外部成交，账本长出 1100 股 |
| 反查报错时一笔都不判（07-30） | 同上 | 原先把「库抖了」当「查不到」→ 当真单入账，一次超时就能造出一笔外部成交 |
| 挂起数字露出通道状态（07-30） | `dispatcher.channel_status().orphan_held` + `ws_smoke status` | 挂起的行不再进 `inbox_pending`，没人报数就是一笔无人知晓的漏账 |

**07-30 午间两笔（都是「协议定了但代码没实现」，不是 bug）**

| 补的东西 | 位置 | 为什么之前看不见 |
|---|---|---|
| **ws 快照对账通路**（协议 §6.2） | `runner._query_loop`（第五个协程）+ `ledger_service.positions_source` + `ws_codec.parse_positions_snapshot` | 协议 §6.2 写着「这是 PMS 侧既有的对账引擎」，实际一行都没有：不发 `query_*`、`snapshot`/`position_update` 落库即 `processed=2` 无人读、`reconcile` 只认 `trading_position` 表。而那张表在新架构下没有写入方——07-30 实测 QMT 已切模拟仓且功能正常，表却是空的（`fetch_positions` 的 `columns` 三个 `None` 就是铁证） |
| **买入前资金校验**（A3 的原意） | `portfolio.cash_view` + `rule_gate._check_cash` | 全系统只有一个 `cash_est = scale − 市值`，那是**从参数算出来的虚数**。scale=200 万而账户真有 98 万，规划器排出的方案规则闸一路放行，要等 QMT 回 `INSUFFICIENT_CASH` 才被拒；而 reject 不自动重发，择时下一跳又算又发又拒——页面看着正常，实际一单也下不去 |
| **偏差可见** | 页面「账户可用」指标 + 偏差 >10% 的 banner（`scaleGap`）；日报关注区 `规模与账户不符` / `资金快照未接通`（阈值 `PMS_SCALE_GAP_ALARM`，默认 0.10） | 上面那条洞之所以到 07-30 才发现，就是因为**页面上完全看不出异常**：只显示 `cash_est`，而它永远等于 `scale − 市值`，看起来总是很充裕。改 `index.html` 前按 07-29 白屏那个坑做了全文体检（无自闭合自定义标签、`el-alert` 8/8、`div` 90/90） |

**对账事实源的三条仲裁**（`positions_source`，ws 为主 / 表为兜底）：① ws 快照新鲜 → 用 ws；
表也非空且对不上 → 照样用 ws 但记 `SOURCE_DISAGREE`（说明表的写入方与 QMT 不同步）② ws
缺失/过期/字段不认 → 退回表并说明**是哪种原因**（三种处理方式完全不同）③ 两个源都**没有应答**
→ `source=none`，本端有持仓则拒绝对账、**force 也不放行**（没有读数可供人工确认，要清账走
`reset_ledger.py`）；本端也空则只留 note 不报 ERROR。
**「应答了空集」≠「没应答」**：表查询成功返回 0 行是有效数据，归 `table` 交给爆炸半径闸处理，
force 能放行——一开始把两者混为一谈，直接把 07-29 那个「下游读空绝不清账」用例的 force 分支挂了。

**资金校验的两条口径**：`scale` 管仓位纪律（该不该买这么多）、`available_cash` 管买不买得起，
两个不同的约束不合并；`cash_avail` 必须含 `sell_return_today`（当日回笼 T+0 可用），否则「卖一只
买另一只」这条最常见的换仓路径会被判成资金不足。拿不到 ws 资金快照时**降级不拦但留痕**
（`CASH_ESTIMATED`）——与研判闸同一口径，一律拒等于把通道故障升级成业务停摆。

**代码格式归一**：ws 快照的 `ts_code` 强制转点式。不转的话 diff 会拿 `SH600000` 比账本里的
`600000.SH`，**每一只都对不上**——账本那只判「下游没了」要核销、ws 那只判「新持仓」要补，
一次格式不一致就能造出一轮双向全量重写，比读空还狠。有单测锁着。

**孤儿成交这条的判断依据**（值得记住的口径）：ws 这条路上的 trade 必带 `instruction_id`（§5.5），
而那个 id 是 PMS 自己生成、自己写进出口表的，所以**反查不到只可能是数据不一致**，不可能是
「有人在 QMT 手工下了单」——手工成交走 `trading_order` 那条路，根本不进 inbox。两种错的代价
并不对称：**漏账看得见**（inbox 留着行、有 ERROR、通道状态报数字），**错账看不见**（凭空长出来的
持仓与真持仓同形，而摊薄成本和安全垫已经全错，补仓/加仓/保垫减仓全挂在安全垫上）。所以不确定时
挂起等人工，不猜。`processed=3` 与 `2`（已消化）必须分开——`2` 的语义是「确认过不用管」，混在
一起事后就分不出哪些是真丢账。要追认：确认这些成交真该入账后，把那些行的 `processed` 改回 `0`。

---

## 5. 待对端（QMT 侧）

R1–R4 已在 07-30 上午验完（结果见 §2）。**R1、R2 的代码校验、R3、R4 均已到位**，
`QMT_TEST_ENV_REQUIREMENTS.md` 的主体可以划掉。剩下三件：

**5.1 `trade_no` 不合协议 §5.5（阻断切换）**

实测值是 `T-SHADOW-6a21…` / `T-SHADOW-9f64…`，协议要求 `{broker_order_id}#{n}`，
即 `SHADOW-7c472c48f0#1/#2/#3`。已核实 PMS 只是原样读 payload 的 `trade_no`
（`ws_codec.py:418` / `runner.py:488`），不自造，所以是对端的格式。

为什么必须改：随机串**当下**能去重（唯一索引照样拦），但它**不确定**。§6.1 的补发场景里，
对端若重新生成一次随机串，同一笔成交就拿到两个不同的 `trade_no` → 第二层去重失效，只剩 seq
一层；而 seq 那层在水位回退或 inbox 被清后也没了 → **重复入账，摊薄成本与安全垫一起错**。
`{broker_order_id}#{n}` 是确定性的，补发多少次都是同一个值——这正是 §5.5 当初定这个格式的理由。

**5.2 价格带校验缺失**

`600000.SH sell 100 @99.99`（浦发涨停约 11.1）既没被拒也没成交，一路挂到 `EXPIRED`。
根因一半在协议：原 §7.3 里 `LIMIT_UP`/`LIMIT_DOWN` 指的是「涨跌停无法成交该方向」，
`BAD_PARAM` 只写了「价格精度超限」，**「限价超出当日涨跌停区间」没有落点**。
协议已升 **V1.0.1**：`BAD_PARAM` 的含义扩为「价格不合法（精度超限或限价越界）」，
并补了与 `LIMIT_UP`/`LIMIT_DOWN` 的分界说明。**消息集与状态机一字未动，V1.0 的实现无需改动即合规。**

**5.3 19 条 `SIG_INVALID` 未查明（签名底座上的问号）**

`pms_qmt_inbox` 里 seq 6299–6317 连续 19 条 `reject{instruction_id: null,
code: SIG_INVALID, reason: "signature verification failed"}`——**是对端验不过我们的签名**。

- PMS 侧日志已随 `force-recreate` 消失，`logs/` 与 `docker compose logs pms-ws` 都翻不到
- **这 19 条消息永久丢了**：`runner` 对 reject 不自动重发。若其中有 `place_order` 或
  `cancel_order`，那就是「发出去了没人执行」，而通道一路显示 ONLINE
- 只能向 QMT 侧要 07-29 的 `signature verification failed` 日志段——他们收到的原始帧一定在
- 顺带一个待补的能力：PMS 侧不留发送侧流水，所以事后无从知道被拒的是哪几条。要不要加，见 §6

**5.4 重建模拟持仓时 `cost_price` 必须是真实成本（新增，最容易被忽略）**

账本空着的时候**爆炸半径闸是完全放开的**（`_recon_blast_guard` 第一行 `if not held: return None`），
而 `daily_settle`（15:10，`apply_fix=True`，休假模式照跑）会把 `trading_position` 里的东西
**无条件**认领进账本。所以对端往那张表里写什么，账本就长成什么。

`ADD_RECON_LOT` 的开仓价优先取下游 `cost_price`，取不到才拿现价兜底。**若 `cost_price` 是 0
或等于现价**，摊薄成本就等于当天价、安全垫齐刷刷是 0——而安全垫是盈利加仓(≥3%)、保垫减仓
(峰值≥6%)、补仓评估档(−8%/−15%)共同的判断依据，一错就是整条纪律链。07-29 首次接管 22 只时
踩过一次，已有单测守着 PMS 侧的取值优先级，但**数据本身对不对只能靠对端**。
`available_quantity`（T+1 可卖）同理，请填合理值。

**5.5 `_sender_loop` 生命周期（`QMT_SIDE_CONTROL_PATH.md` §5.1，仍未得答复）**

队列绑定（每轮重读 `self._send_queue`）与 socket 绑定（创建时绑死）生命周期不一致，重连
频繁时旧 sender 会从新队列取消息发往已关闭 socket，消息静默丢失。**这条与 5.3 的现象可以
互相解释**（都是「消息发出去了但对端没正确收到」），一起问更省事。

---

## 6. 下一步

1. ~~确认对端实现了 R1–R4 的哪几条~~ ✅ 07-30 上午完成，结果见 §2
2. ~~清账重来~~ ✅ 07-30 11:14 完成，基线见 §3.0
3. **发函 QMT 侧**（§5.1~5.5 五条，见 `QMT_SIDE_S3_CLOSEOUT.md`）
4. **等对端答复 §5.1（那 1100 股的来历）再认领账本**。`pms-beat` 现在停着，所以 15:10 不会
   自动建账。答复回来后：是联调残留 → 请对端清掉、我方不认领；是真持仓 → 跑
   `curl -X POST '.../api/ops/reconcile?apply_fix=true'` 认领，然后 `--profile sched up -d pms-beat`。
   探数据用 `apply_fix=false`（只看不改）或 `ws_smoke.py inbox --type snapshot --width 600`
5. **账本重建完立刻把 `PMS_SIGNAL_ENABLED` 打开**（见 §7 最后一条）
6. **盘中**跑 `scan-proposals?dry_run=true` + `exec-tick?dry_run=true`，看真实候选清单
7. 日终对账零差异 → S3 完整通过
8. 两边都确认，再切 `PMS_DISPATCH_MODE=ws`

第 6 步必须在**交易时段**做，原因见下。

---

## 7. 已知的坑（别再踩）

**`docker compose restart` 不重载代码。** 源码是 `COPY . .` 打进镜像的，`restart` 只是
重启老容器。改完代码要生效：`./scripts/deploy.sh`，或在开发机上
`cp docker-compose.dev.yml docker-compose.override.yml` 挂载源码（此后 `restart` 才有效，
但改 `requirements.txt` 仍需 build）。**这个坑吃掉过一整轮排查。**

**账本空的时候，对账的爆炸半径闸是完全放开的。** `_recon_blast_guard` 第一行就是
`if not held: return None  # 空账本 → 建账/认领, 放行`，这是为首次建账留的口子。代价是：空账本
期间 `trading_position` 里出现什么，15:10 的 `daily_settle` 就无条件认领什么（`apply_fix=True`，
且 `respect_exec_halt=False` 休假模式照跑）。盘中那个轻对账是 `apply_fix=False`，只看不改，
所以**风险窗口只有 15:10 这一次**。对端持仓没稳定前，停 `pms-beat` 比事后再清一遍账省事。

**账本空的时候消化信号会把信号 ACK 掉。** `_handle` 判 `ACT_IGNORE` 之后照样 `_ack(db, key, msg_id)`
——而账本空 → `positions_view()` 取不到持仓 → 所有卖出信号一律 IGNORE。真实持仓在 QMT 那边，
那些本该处理的风控卖出会被消费组静默吃掉，跨日再也拿不回来。所以清账期间 `PMS_SIGNAL_ENABLED=False`
是对的，**但账本重建完必须立刻打开**。（候选改进：IGNORE 原因是「账本无此持仓」时不 ACK，
或账本为空时整体跳过而非消费——与孤儿成交同一类毛病，丢的东西重建不回来且一声不响。）

**出口表被清过（或换过环境）会造出「孤儿成交」。** inbox 里的 trade 带着 instruction_id，
出口表里却没有对应行——`SMOKE_` 隔离的判据正是反查出口表，所以那道闸对孤儿成交**完全失效**。
07-30 之前这类成交会被当成外部成交并入 BASE；现在改为挂起（`processed=3`）+ ERROR 告警。
**上下游停机但遗留数据没清时最容易撞上**，重建账本前先看一眼 `ws_smoke status` 的「挂起待人工」。

**`pms_ws_state.last_seq` 运行时手改无效。** 两条机制会撤销它：`_shutdown` 会把内存水位
刷回库；`_boot` 会用 `inbox_recover_watermark` 顺着 inbox 连续段走回去。要造缺口用
`ws_smoke rewind`（它会拒绝在 pms-ws 运行时执行，也会拒绝跨过已入账的成交）。

**对端模拟环境按限价全成、不校验代码。** 一张 99.99 的浦发卖单（实际价 10 元）会全成，
`999999.SH` 也会全成。**任何测试单都会产生成交回报**——所以联调单隔离（`SMOKE_` 前缀）
是必需的，不是可选的。

**收盘后的 dry run 看不出东西。** 取不到实时价时 `positions_view` 用摊薄成本兜底当现价，
安全垫齐刷刷归零，DCA/ADD/TRIM 三个评估器全不触发，结果永远是 `candidates: 0`。
判断"切了 ws 会发生什么"必须在交易时段跑。

**`pong` 带 seq（符合 §5）。** 5 秒一条、一天约 1.7 万行进 `pms_qmt_inbox`。
看 inbox 记得用 `ws_smoke inbox --type trade` 过滤，否则全是 pong。

**协议 `reject` 不带 `instruction_id` 时是「协议级拒绝」**——拒的是消息本身不是委托，
走完全不同的分支。对端曾因未实现 `ack_seq` 而回 `unknown type ack_seq`，形成
「我们 ack → 对端拒 → 拒绝带 seq → 我们又要 ack」的 2 秒自激循环，通道显示 ONLINE
但只在刷 reject。

---

## 8. 文档欠账

**✅ 已清（2026-07-30，用户批准）**：`QMT_WS_PROTOCOL.md` §11 变更记录里 V1.0 那行原本
排在 V0.9.2 上面，而 `ack_seq` 恰恰是 V0.9.2 补进来的——对端从上往下读到「V1.0 定稿」
就停，`ack_seq` 因此被漏掉，直接导致了 §7 那个自激循环。现已改为
V0.9 → V0.9.1 → V0.9.2 → V1.0。**纯调两行顺序，条款一字未动**（总行数不变，可 `git show` 核）。

**遗留一项（待定夺，暂不动）**：端点在 `README.md`「ws 通道实现清单」与协议 §11 的 V1.0
那行里都写作 `ws://192.168.16.98:8080`，而 `config/settings.py:94` 实际是
`ws://192.168.16.98:9443/pms`（提交 `0a1a932 调整端口`）。**代码是对的、文档是旧的**，
联调不受影响（运行时读 settings / 运行参数，不读文档），但下一个接手的人会按文档去连 8080。
改的是定稿协议正文里的一处事实值，故未擅动。
