4.4 KiB
4.4 KiB
pbl_domain_ext — PBL 基础域薄扩展(M8)
world / scene / entity 三模块的 PBL 侧薄扩展:为复用平台的世界/场景/实体叠加 租户 / 蓝图 / 班级 / 团队关联维度。不改三张基表结构、不侵入复用模块代码(Q-OPEN-3 裁决:零改表)。
核心事实
- 自有表 1 张:
pbl_domain_ref(UNIQUE(tenant_id, ref_type, ref_id))- 权威 DDL:
projects/pbls/docs/01-design/data-model.md§J1 - 表总账:
projects/pbls/pbls_spec.json→tables_by_module.pbl_domain_ext = 1、tables_total = 36
- 权威 DDL:
- 契约 13 个:设计
projects/pbls/docs/01-design/modules/pbl_domain_ext.md§3.1(5) + §3.2(5) + §3.3(3) - 复用基表只读:world / scene / entity 零 ALTER、零写入
- 他模块表只读:
pbl_governance.pbl_team_member(取团队成员,表缺失时降级空列表)
目录结构
pbl_domain_ext/
├── pbl_domain_ext/ # Python 包(模块名 = 包目录名,无 app.py)
│ ├── __init__.py # ② 导出 load_pbl_domain_ext + 13 契约
│ ├── init.py # ③ load_pbl_domain_ext():注册 env.pbl_* + 设计原名;OWN_TABLES
│ ├── api.py # ① 13 个契约接口实现(设计 §3)
│ ├── base.py # 复用基表只读投影层(列名运行时探测、悬挂引用过滤)
│ ├── db.py # 数据访问适配(SqlorAdapter 生产 / SqliteAdapter 测试)
│ └── errors.py # PBL_E_* 错误码 + 统一异常(优先复用 pbl_common)
├── models/pbl_domain_ref.json # 表定义四段式(summary 数组 / fields / indexes / codes)
├── json/pbl_domain_ref.json # CRUD 浏览定义(tblname + params.browserfields/editable)
├── sql/pbl_domain_ext.sql # 建表 DDL(对齐 data-model.md §J1)
├── wwwroot/
│ ├── index.ui # 模块入口页(三组契约卡片导航)
│ └── api/*.dspy # 13 个契约端点薄封装(与 api.py 一一对应)
├── scripts/load_path.py # RBAC 路径显式注册(13 dspy + 1 ui,禁通配符)
├── tests/ # 离线 sqlite 测试(62 用例,覆盖 13 契约 + 薄扩展铁律)
├── skill/SKILL.md # Agent 必读规范(铁律 + 陷阱 + 契约映射)
├── pyproject.toml
└── README.md
契约清单(设计 §3 → 实现 → 端点)
| # | 接口 | 实现 | dspy 端点 |
|---|---|---|---|
| 1 | bind_ref |
api.py:bind_ref |
api/pbl_domain_ref_bind.dspy |
| 2 | unbind_ref |
api.py:unbind_ref |
api/pbl_domain_ref_unbind.dspy |
| 3 | get_ref |
api.py:get_ref |
api/pbl_domain_ref_get.dspy |
| 4 | list_refs |
api.py:list_refs |
api/pbl_domain_ref_list.dspy |
| 5 | update_ref |
api.py:update_ref |
api/pbl_domain_ref_update.dspy |
| 6 | list_worlds_by_tenant |
api.py:list_worlds_by_tenant |
api/pbl_world_list_by_tenant.dspy |
| 7 | list_scenes_by_world |
api.py:list_scenes_by_world |
api/pbl_scene_list_by_world.dspy |
| 8 | list_entities_by_scene |
api.py:list_entities_by_scene |
api/pbl_entity_list_by_scene.dspy |
| 9 | get_world_with_pbl_context |
api.py:get_world_with_pbl_context |
api/pbl_world_get_context.dspy |
| 10 | check_ref_access |
api.py:check_ref_access |
api/pbl_domain_ref_check_access.dspy |
| 11 | list_teams_by_class |
api.py:list_teams_by_class |
api/pbl_team_list_by_class.dspy |
| 12 | bind_team_to_world |
api.py:bind_team_to_world |
api/pbl_team_bind_world.dspy |
| 13 | get_team_worlds |
api.py:get_team_worlds |
api/pbl_team_world_list.dspy |
挂载
from pbl_domain_ext import load_pbl_domain_ext
load_pbl_domain_ext(env) # 注册 13 契约到 ServerEnv
import sys; sys.path.append('modules/pbl_domain_ext/scripts')
import load_path; load_path.register(env) # RBAC 路径注册(幂等)
模块 host-agnostic:只依赖 sqlor / ahserver ServerEnv / 自有表,不依赖宿主入口与配置。
验证
python3 -m py_compile pbl_domain_ext/*.py scripts/load_path.py tests/*.py
python3 tests/test_domain_ref.py # 62 tests OK
python3 scripts/load_path.py # 路径注册自检 OK
详见 skill/SKILL.md(铁律、陷阱、需求追溯)与 docs/work-log-2026-09-18.md(本轮 QC 退回逐条整改记录)。