pbl_runtime_ext/docs/work-log-2026-09-22-rtx0005.md
agent.develop f91aa2e7c6 test(PBL-RTX-0005): 核验性门禁回归取证入库(响应 QC #10)
- tests/evidence/rtx0005_gate_regression_20260922.txt(16767B): 本任务内重跑并原样落盘
  [1] pbl_runtime_event_ddl.py --verify rc=0(DELIMITER 配对/过程体无非法 RETURN/门禁自检坏样本可检出)
  [2] pytest tests/ rc=0 9 passed  [3] m11b_selftest.py rc=0 110 PASS 0 FAIL
- docs/work-log-2026-09-22-rtx0005.md: 追加 §7 第2轮收口——如实写明修复代码本体源自
  前序提交 dfffebb(引擎代为收口),本轮为取证/门禁/文档收口,未重写修复代码;
  并记录 QC #9 sd_bugs 状态机实测不过(start_fix/fix_bug 均 FAIL: Bug 不存在)未伪造
- 选择性 git add 2 项,未使用 git add -A
2026-09-22 15:24:50 +08:00

140 lines
10 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 库。
---
## 7. 第 2 轮收口(2026-09-22 15:17~15:26,响应 QC #8/#9/#10)
### 7.1 修复代码归属澄清(QC #10)
DELIMITER / 非法 `RETURN` 的**根因修复代码本体**来自前序提交 `dfffebb`(引擎代为收口,
含 `scripts/pbl_runtime_event_ddl.py` +139、`scripts/patch_rtx0005.py` 新增 231、
`tests/evidence/rtx0005_live_evidence.py` 新增 186、`tests/test_m11b1a_ddl_runtime.py` +29、
`sql/migrations/20260919_m11b_02|03`、`sql/m11b_partitions.sql`)。
上一轮 agent 自署名提交 `c3726dd` 只含 docs + evidence .txt(+98/-2)。
本轮**不声称重写了修复代码**,而是在本任务内做一次显式的**核验性提交**:把修复代码的
回归门禁结果原样落盘并入库 —— `tests/evidence/rtx0005_gate_regression_20260922.txt`(16767B)。
### 7.2 核验性门禁回归(原样输出已落盘,HEAD=c3726dd,15:22:32 +0800)
| 段 | 命令 | rc | 关键行 |
|---|---|---|---|
| [1] | `.venv/bin/python scripts/pbl_runtime_event_ddl.py --verify` | 0 | `PASS DELIMITER 语句完整性: 4 个产物 DELIMITER 配对正确、27 个 $$ 段首关键字完整、无裸 CREATE$$/DROP$$ 残缺行`;`PASS 过程体无非法 RETURN(PBL-RTX-0005 门禁)…append-only 守卫完整保留`;`PASS 非法 RETURN 门禁自检:坏样本(含 RETURN;)被检出 1 条、好样本(修复后守卫)零误报`;末行 `VERIFY PASS` |
| [2] | `.venv/bin/python -m pytest tests/ -v --tb=short` | 0 | `collected 9 items` / `9 passed in 0.40s` |
| [3] | `.venv/bin/python scripts/m11b_selftest.py` | 0 | `总计 110 项,PASS 110,FAIL 0` / `RESULT: PASS` |
另本轮重跑 `bash tests/run_m11b1a_localdb.sh` → rc=0,`[汇总] 共 29 项,PASS 29,FAIL 0` /
`HARNESS PASS`;[B] 实库层 B1「分区 7 个 / 维护过程 2 个 / 触发器 2 个」、B3
`CALL ensure_partitions(9)` 分区 7→11、B4 prune DROP p202001 剩余 11 个。
### 7.3 git 收口(QC #8)
- 本模块仓:选择性 `git add tests/evidence/rtx0005_gate_regression_20260922.txt docs/work-log-2026-09-22-rtx0005.md`(禁 -A)+ commit(Author=agent.develop)。
- `projects/pbls` 仓:逐项 add `docs/02-develop/dev-notes-rtx0005-ddl-1064-fix.md`、
`m11b2c-localdb-fix-run.log`、`dev-notes-rtx0005-round2-closure.md`;
越界改动 `m5b-four-types-wip.patch` 已 `git checkout --` 回滚(6537B 复原,porcelain 为空);
其余未跟踪文件(deliverables/*、m5a-*、m11b2c-anchor2-*)不属本任务,未 add、未删,如实声明。
### 7.4 sd_bugs 状态机(QC #9)实测不过,未伪造
`start_fix('PBL-RTX-0005')` → `FAIL: Bug 不存在`;`fix_bug('PBL-RTX-0005')` → `FAIL: Bug 不存在`;
`query_project_data(sd_bugs)` 全表 1 行(2026-09-18 无关 closed 部署前置 Bug)。
start_fix/fix_bug 只做状态迁移不建行,develop 无 report_bug 能力,且 classify_task 依 PM
params 判定 `task_kind=new_dev`。需 PM 先在 sd_bugs 登记本缺陷行(iteration_id='pbls-初始迭代')
并把 task_kind 改 `bug_fix`,或将本任务交付本体认定为「代码 + 门禁回归 + 实库取证」。
详见 `projects/pbls/docs/02-develop/dev-notes-rtx0005-round2-closure.md` §3。