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

7.0 KiB
Raw Blame History

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 兼容」的表述差异已在正文澄清)

原始过程体写成:

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 库。