pbl_compiler/docs/work-log-2026-09-19.md

8.6 KiB
Raw Permalink Blame History

pbl_compiler 工作日志 — 2026-09-19M3b 规则映射与导出 · 整改轮)

任务:[M3b] pbl_compiler script_engine 规则映射与导出 第12章 event→condition→response → script_type=1 规则 JSON 映射、产物导出、game_definition 写入) 角色agent.develop 迭代pbls-初始迭代 任务性质new_dev含 QC 退回意见逐条整改)

1. 本轮范围

只做「登记面接线 + 审计工具自身缺陷 + 提交可追溯性」的增量整改,不重写已合规的 models/ 表定义本体(前轮 QC 已确认四段式 / primary str32 / codes parentid 全过)。

# 退回意见 处置
QC #1硬门禁·第四章 RBAC 5 个 M3b Web 契约未登记 RBAC 路径init.py 注释条数与代码不符 已修:scripts/load_path.py 逐条显式登记(无通配符),pbl_compiler/init.py 注释与事实对齐
QC #2流程·真实性 交付前未自行 git commit由引擎代为收口 已修:本轮 agent 自行选择性 git add + git commit + git pushcommit cb1132e
前轮 #2GD 唯一写入口) gd_rules_writer 无调用入口 保持:pbl_compiler/api.py L606 编译主流程 ⑥.5 调用 write_gd_rules()rules_export_api.py L223 亦经此入口
前轮 #3CRUD editable editable 仅 get_data_urlxls2ui 会回退默认写入口 保持方案 A9 个只读拒绝端点 + params 顶层三 URL 绝对路径
前轮 #4work log 无 dated work log 本文件补齐归档

2. 时间线

  1. 实跑审计定位根因python3 scripts/audit_rbac_parity.py → rc=1报 「load_path.py PATHS 为空RBAC 零登记 → 全部 403」。
  2. 交叉核验发现是两处事实叠加
    • 工作区 scripts/load_path.py 实际已登记 29 条(grep -c "('/pbl_compiler/api/" = 29ls wwwroot/api/*.dspy | wc -l = 29 一致 → QC 引用的「仅 15/20 条」是 git HEAD 版本(前轮变更未提交,git show HEAD:scripts/load_path.py 实测 20 条、 git ls-tree HEAD wwwroot/api/ 实测 20 个),审核方读的是仓库而非工作区。
    • 审计脚本自身存在解析缺陷:parse() 对纯字面量列表已 literal_eval 成 python listresolved 字典只收 ast.List 形态,导致 PATHS = PATHS_CONTRACTS + PATHS_READONLY_DENY BinOp回查 resolved 拿到空列表 → 把已登记的 29 条误判成「零登记」,产生假 FAIL。
  3. 修审计工具resolved 同时接受 list(已求值)与 ast.List(含函数引用求值失败)两种形态。
  4. 修注释init.py 文件头「共 20 条 + 只读列表 CRUD 6 条」→ 「共 29 条 = Web 契约端点 20 + CRUD 只读拒绝端点 9无通配符」。
  5. 实跑自证audit rc=0 PASSscripts/test_m3b_mapping.py PASS=113 / FAIL=0 python3 -m py_compile pbl_compiler/*.py scripts/*.py OK。
  6. 自行收口:选择性暂存 15 个文件6 改 + 9 新增 .dspygit commitcb1132e git push origin HEAD 成功(d203811..cb1132e HEAD -> main)。未使用 git add -A __pycache__ / 生成物未入库。

3. 技术决策与陷阱

  • RBAC 登记分两个集合而非一个PATHS_CONTRACTS20进 init.py CONTRACTS / init.py __all__ / wwwroot/apiPATHS_READONLY_DENY9不是 ServerEnv 契约, 只为封死 xls2ui 默认 add_/update_/delete_<table>.dspy 写入口)。审计按 CONTRACTS READONLY_DENY 比对,既不漏登记也不产生幽灵登记。
  • 只读表为何仍要建 create/update/delete 端点crud-definition-spec 要求 editable 三 URL 齐备,缺项时 xls2ui 回退生成默认写入口 → rules_hash29.6 确定性指纹)可被手工改写。 故 9 个端点显式返回 {"widgettype":"Error","options":{"label":"...只读,禁止手工增删改"}} 把「拒绝」变成可机械验证的事实audit 第 ⑪ 项检查 Error widget
  • 不登记不存在的路径QC #1 提到「若引入 pbl_script_rule 只读列表 CRUD 生成目录则补 6 条」。 实测 wwwroot/ 下仅有 api/ 一个子目录(无 CRUD 生成目录),pbl_script_rule_list 是手写 Web 契约而非 xls2ui CRUD → 补登 /pbl_compiler/pbl_script_rule 等 6 条会形成幽灵登记、 污染 permission 表。此判断已固化进 audit 第 ⑫ 项检查。
  • 禁通配符29 条全部显式audit 第 ④ 项用正则扫 */% 通配命中即 FAIL。
  • 审计工具也要被审计resolved 只认 AST 形态这一缺陷,会让「已正确整改」被判成 「RBAC 零登记」,白白烧掉退回预算。凡登记面比对,脚本必须同时兼容字面量求值成功/失败两种形态。

4. 验证(实跑输出摘录)

$ python3 scripts/audit_rbac_parity.py
  PASS init.py CONTRACTS = 20 个契约
  PASS 20 个契约在 api.py/rules_export_api.py 均有同名实现
  PASS __init__.py __all__ 覆盖全部 20 个契约
  PASS load_path.py 无通配符29 条全显式)
  PASS load_path.py 登记 29 条无重复(契约 20 + 只读拒绝 9
  PASS PATHS_CONTRACTS 与 CONTRACTS 一一对应20 条)
  PASS PATHS 登记 29 条,与期望端点集合(契约 20 + 只读拒绝 9一一对应
  PASS wwwroot/api/*.dspy = 29 个,与 CONTRACTSREADONLY_DENY 一一对应
  PASS grep 口径自证PATHS 中 /api/ 条目=29wwwroot/api/*.dspy=29
  PASS 29 个 .dspy 无非法 import仅允许 sqlor.filter
  PASS 29 个 .dspy 均有显式 return
  PASS .dspy 无 ServerEnv() 取请求态
  PASS 9 个只读拒绝端点均显式返回 Error widgetCRUD 写入口已封死)
  PASS wwwroot/ 无 CRUD 生成子目录(只读列表走手写契约 api/pbl_script_rule_list.dspy
  PASS json/*.json 共 3 个:根键白名单(['_comment','alias','params','tblname','title']) / alias
       / editable 三 URL 齐备且指向真实 .dspy / 字段与 models 全对齐
RESULT: PASS (contracts=20, readonly_deny=9, dspy=29, rbac_api_paths=29, json=3)   rc=0

$ python3 scripts/test_m3b_mapping.py
PASS: 113   FAIL: 0

$ grep -c "('/pbl_compiler/api/" scripts/load_path.py   → 29
$ ls wwwroot/api/*.dspy | wc -l                          → 29
$ grep -n 'pbl_compiler_export_rules|pbl_compiler_rules_preview|pbl_compiler_rules_diff|
          pbl_game_definition_rules_get|pbl_script_rule_list' scripts/load_path.py
  → 68,69,70,71,72 五行命中5 个 M3b 契约全部显式登记)
$ git log --oneline -1 → cb1132e fix(pbl_compiler): M3b RBAC 29条显式登记+...
$ git push origin HEAD → d203811..cb1132e  HEAD -> main

5. 环境受限项(如实说明,不谎报已验证)

  1. ~/repos/sage 不存在QC 改法要求 cd ~/repos/sage && ./py3/bin/python ~/repos/pbl_modules/pbl_compiler/scripts/load_path.py 并「同步中央 sage/load_path.py 兜底」。本工作空间实测 ls -d ~/repos/sage → 无该目录, 中央 sage 仓库与 py3 虚拟环境均不在位;apps/pbls/ 下也没有中央 load_path.py (全库 grep -rln "pbl_compiler/api/" apps/ 零命中),各 pbl_* 模块一律以 modules/{模块}/scripts/load_path.py 为唯一登记面。故本轮只完成模块侧登记与自证, 中央兜底无法执行,需部署角色在有 sage 的环境跑 register()
  2. 未连库、未起服务register() 依赖 rbac CLIset_role_perm.py)与 MariaDB 本工作空间无 DB 实例(PBLS_DB_USER 空、mysql 未授权)。脚本设计为 CLI 不在位时 打印 PENDING 清单并以 rc=1 暴露(不静默跳过),部署阶段据此补登。
  3. 未重跑 xls2ui/build.shwwwroot/ 无 CRUD 生成子目录(三表按只读列表呈现, 走手写契约),本轮无 .ui 产物需再生成;若后续引入 CRUD 目录audit 第 ⑫ 项会 FAIL 提醒补登。
  4. 「登录后调用不再 403」未做端到端实测:受 1/2 限制,只能以「登记面与端点集合一一对应」 作为可达性的机械证明,真实 HTTP 200 验证需部署环境。

6. 分支状态

  • 仓库:modules/pbl_compilerorigin git@git.opencomputing.cn:yumoqing/pbl_compiler.git
  • 分支:mainHEAD = cb1132eagent.develop 自行提交并推送,非引擎代为收口)
  • 工作区:暂存区已清空;未跟踪仅剩 docs/work-log-2026-09-19.md(本文件,随交付入库) 与 __pycache__.gitignore 已排除)
  • 前序 6 个 deliver: 交付收口(引擎代为提交) 提交626b2c0/eb18a7d/4051e9d/c276af5/2c14bf5/d203811 为历史事实,本轮不改写历史,仅在其上追加 agent 自有提交。