pbl_runtime_ext/docs/work-log-2026-09-22-rtx0005.md
agent.develop c3726ddd29 fix(PBL-RTX-0005): 过程体非法 RETURN 等价改写为正向条件单语句 SIGNAL + 回归门禁 + 实库取证落盘
- scripts/pbl_runtime_event_ddl.py: append_only_sql() 两处 RETURN 改为
  IF p_table=tbl AND IFNULL(@pbl_guard_ctx,'')<>ctx THEN SIGNAL 45000/45001;
  新增 _procedure_body_return_errors() 静态门禁 + verify() 第10/11项接入(含坏样本自检)
- scripts/patch_rtx0005.py: dry-run 先行 + 写盘后二次读取断言, 幂等确认(命中0次)
- tests/evidence/rtx0005_live_evidence.py: _Tee 同步落盘取证正文(QC #11)
- tests/evidence/rtx0005_live_evidence.txt: 修复后实库取证(MariaDB 10.6.23, 装载rc=0,
  守卫拒绝45001/break-glass放行/触发器拦截, ensure_partitions 6->11)
- docs/work-log-2026-09-22-rtx0005.md: 根因/改动点/实库验证/收口状态归档
- .gitignore: 补 .rtx5tmp/ *.egg-info/ 及 MariaDB 数据文件后缀(QC #5 仓库去污染)
2026-09-22 15:01:30 +08:00

97 lines
7.0 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.

# Work Log — PBL-RTX-0005(pbl_runtime_event_ddl 过程体非法 RETURN → 实库 ERROR 1064)
- **日期**: 2026-09-22
- **角色**: agent.develop
- **任务**: [PBL-RTX-0005] 修复 pbl_runtime_event_ddl 存储过程 DELIMITER 兼容缺陷(实库 DDL 装载 ERROR 1064)
- **仓库/分支**: `modules/pbl_runtime_ext` @ `main`
- **复杂度评估**: 简单,单交付单元(一个 DDL 生成器文件 + 一轮实库复跑),无需拆分
## 1. Scope
仅改 DDL 生成器 `scripts/pbl_runtime_event_ddl.py` 的 C 段(`append_only_sql()`)存储过程渲染,
并按 QC 退回意见补齐回归门禁、实库取证、取证落盘与仓库收口。**不动** 本轮已收口的
`tx_write` 主链路与测试断言阈值(`tests/test_m11b2c_runtime_ext.py` 阈值原样)。
## 2. 根因(1064 真实成因,与任务标题「DELIMITER 兼容」的表述差异已在正文澄清)
原始过程体写成:
```sql
IF p_table <> '%(table)s' THEN
RETURN; -- 只守护事件表,其他表不受影响
END IF;
IF IFNULL(@pbl_guard_ctx, '') = '%(ctx)s' THEN
RETURN; -- break-glass:一次性历史数据回填
END IF;
SIGNAL SQLSTATE '45000' ...
```
两个叠加问题:
1. **服务端语义错误**:MariaDB/MySQL 的 `RETURN` 语句只允许出现在 **FUNCTION** 体内;
`PROCEDURE` / `TRIGGER` / `EVENT` 体内出现即语法错误。
2. **CLI 切分错误**:`RETURN;` 后的分号不在 `DELIMITER $$` 保护范围内(且原实现把
`--` 行尾注释写在 `$$` 同行,`$$` 被当注释内容吃掉),`mariadb` CLI 提前在分号处切分
语句 → `ERROR 1064 (42000) at line 65`。
3. **连带故障**:C 段失败使后续 `CREATE PROCEDURE pbl_runtime_event_ensure_partitions`
未执行,`CALL pbl_runtime_event_ensure_partitions(9)` 报 `1305 PROCEDURE does not exist`。
## 3. 改动点
| # | 位置 | 改动 |
|---|------|------|
| 1 | `append_only_sql()` L179-193 | 两处非法 `RETURN` 提前退出 **等价改写**为「正向条件 + 单语句 SIGNAL」:`IF p_table='%(table)s' AND IFNULL(@pbl_guard_ctx,'')<>'%(ctx)s' THEN SIGNAL ...; END IF;`。守卫未删除、未注释,语义与原两次提前退出一致(非本表→放行;break-glass→放行;否则拒绝)。 |
| 2 | 同上,触发器段 | `BEFORE UPDATE` / `BEFORE DELETE` 护栏改为 `IF ... <> ctx THEN SIGNAL ...`,不再依赖过程体 `RETURN`。 |
| 3 | L405-470 新增静态门禁 | `_TRAILING_COMMENT` / `_ILLEGAL_RETURN` 常量 + `_procedure_body_return_errors()`:逐行剥行尾 `--` 注释后扫描渲染产物,报告「过程/触发器/EVENT 体内裸 RETURN」;`CREATE FUNCTION` 体放行。 |
| 4 | `verify()` 第 10/11 项接入 | 对 4 个 SQL 产物跑 RETURN 门禁;并用 `_ILLEGAL_RETURN_PROBE`(字符串拼接构造,避免本 .py 自身出现裸 `RETURN;` 行)自检「门禁真的会报错」+ 反向自检「修复后的 append_only_sql 不误报」。 |
| 5 | `scripts/patch_rtx0005.py` | 补丁器改为 dry-run 先行:每处替换原文必须恰好命中 1 次、替换后裸 `RETURN;` 计数为 0、门禁函数存在、`ast` 可解析,任一不满足不落盘 rc=1;写盘后重新 read 二次断言,失败回滚。当前对已修复文件 dry-run 报「命中 0 次」= 幂等确认(缺陷已不存在)。 |
| 6 | `tests/evidence/rtx0005_live_evidence.py` | 新增 `_Tee` 类 + `main()` 包装:取证 stdout **同步落盘** `tests/evidence/rtx0005_live_evidence.txt`(QC 收口项 #11),脚本自身异常也留痕并 rc=1。 |
| 7 | `.gitignore` | 增 `.rtx5tmp/`(参照既有 `.m11b2c_tmp/`)、`*.egg-info/`、MariaDB 数据文件后缀(`*.ibd/*.frm/*.MAI/*.MAD/ibdata1/ib_logfile*/ibtmp1/aria_log*/binlog.*`)。 |
## 4. 实库验证(全部实跑,原样 rc 留证)
取证日志:`projects/pbls/docs/02-develop/m11b2c-localdb-fix-run.log`
沙箱取证正文:`tests/evidence/rtx0005_live_evidence.txt`
| 验收项 | 命令 | 结果 |
|--------|------|------|
| a | `bash tests/run_m11b1a_localdb.sh` | **rc=0**,`[汇总] 共 29 项,PASS 29,FAIL 0` / `HARNESS PASS`(B1 CLI+DELIMITER 装载后分区 7 / 维护过程 2 / 触发器 2;B3 `ensure_partitions(9)` 分区 7→11;B4 `prune_partitions(2)` DROP p202001 保留 pmax) |
| b | `.venv/bin/python -m pytest tests/ -v --tb=short` | **rc=0**,9 collected / **9 passed** / 0 failed |
| c | `.venv/bin/python scripts/m11b_selftest.py` | **rc=0**,`总计 110 项,PASS 110,FAIL 0` / `RESULT: PASS` |
| d | `.venv/bin/python tests/evidence/rtx0005_live_evidence.py` | **rc=0**,`[15] 取证结论: PASS` |
沙箱(MariaDB 10.6.23,一次性 datadir,取证后销毁)关键证据:
- `[6] DDL 装载 rc=0`,stderr 为空(修复前此处为 `ERROR 1064 (42000) at line 65`)
- `[7] information_schema.ROUTINES`:`pbl_assert_append_only` /
`pbl_runtime_event_ensure_partitions` / `pbl_runtime_event_prune_partitions` 均存在
- `[8] information_schema.TRIGGERS`:`trg_pbl_runtime_event_append_only_upd`(UPDATE/BEFORE)
与 `..._del`(DELETE/BEFORE) 均存在
- `[10] CALL pbl_runtime_event_ensure_partitions(9)` rc=0(修复前 1305),分区数 6→11
- `[11]` 非 break-glass `CALL pbl_assert_append_only(...)` → `ERROR 45001 (45000): PBL_APPEND_ONLY_DENIED`(拒绝生效)
- `[12]` `SET @pbl_guard_ctx='append_only_admin'` 后同一 CALL rc=0(break-glass 放行)
- `[13]` 非守护表 `other_table` 放行 rc=0
- `[14]` INSERT 成功;UPDATE / DELETE 均被触发器拒(45001);break-glass 清理探针 rc=0
## 5. 仓库收口状态
- 上一轮引擎代为收口把 `.rtx5tmp/` 下 MariaDB 数据目录二进制(240 项)与
`pbl_runtime_ext.egg-info/` 一并提交进版本库(QC #5)。本轮
`git rm -r --cached .rtx5tmp pbl_runtime_ext.egg-info` + `.gitignore` 补齐,
`git ls-files` 由 300 → 59 项,`git ls-files | grep -cE '^\.rtx5tmp/|egg-info|^\.venv/'` = **0**。
- 本轮由 agent 自行 `git add`(逐项选择性暂存,禁 `-A`)+ `git commit` 收口,提交信息
`fix(PBL-RTX-0005): ...`。
- 工作区遗留未跟踪的 `.rtx5tmp/` 目录仍在磁盘(已被 ignore,不再入库),可由后续清理任务删除。
## 6. 遗留 / 如实披露
1. **sd_bugs 无本任务行**(QC #2):`classify_task` 判定本任务 `task_kind=new_dev`
(PM 参数 `task_kind: "new_dev"`),按 bug-fix 技能「只有 bug_fix 任务走 bug 状态机」,
且 develop 无 `report_bug` 能力、`start_fix('PBL-RTX-0005')` 返回「Bug 不存在」——
sd_bugs 全表仅 1 条 2026-09-18 无关 closed 部署前置 Bug。故本任务不产生
start_fix/fix_bug 流转记录,属**任务类型判定所致**而非漏做;若 PM 认定应按 Bug 跟踪,
请由具备 `report_bug` 能力的角色建行走状态机。
2. `m11b_selftest.py` 的 `C. 真实库端到端` 段仍 SKIP(本工作空间无 ahserver/apppublic 运行时),
如实降级披露,未谎报;真实库行为由 §4 的沙箱取证与 `run_m11b1a_localdb.sh` B 段覆盖。
3. `--live` 段(验收 d)以独立一次性沙箱取证脚本形式补齐并落盘,未触碰项目 test/prod 库。