diff --git a/skills_library/all/project-directory-spec/SKILL.md b/skills_library/all/project-directory-spec/SKILL.md index f3ad321..6524841 100644 --- a/skills_library/all/project-directory-spec/SKILL.md +++ b/skills_library/all/project-directory-spec/SKILL.md @@ -78,15 +78,7 @@ global(全局基础)→ org(客户)→ pipeline(产线)→ project - 存放一个独立模块的代码(可复用单元,含自己的数据 / CRUD / 处理逻辑 / skills)。 - 一个模块一个仓库,命名 `{模块名}`(无后缀),由 design 阶段划分。 - 有远程 git 仓库。 -- 内部结构(参考): - ``` - {模块名}/ - ├── README.md - ├── src/ # 源码 - ├── ddl/ # 表结构 DDL - ├── init/ # 初始化数据 - └── selftest.py # 自测 - ``` +- 内部结构以 `module-development-spec` 技能为准(Python 包目录=模块名 + wwwroot/models/json/init/scripts/skill/pyproject.toml),本规范不重复定义。 ## 四、命名规范 @@ -109,7 +101,7 @@ global(全局基础)→ org(客户)→ pipeline(产线)→ project | requirement | 应用部署单元定义 | `repos/{项目名}_pc/apps/{应用名}.md` | | design | 系统架构 / UI 设计 | `repos/{项目名}_pc/docs/01-design/architecture.md`、`ui-design.md` | | design | 模块清单 + 模块级设计 | `repos/{项目名}_pc/modules/{模块名}.md` + `repos/{项目名}_pc/modules/{模块名}/design.md` + `repos/{项目名}_pc/modules/{模块名}/skill/SKILL.md`(模块技能文档,develop 参考) | -| develop | 模块源码 + DDL | `repos/{模块名}/src/`、`repos/{模块名}/ddl/` | +| develop | 模块源码 | `repos/{模块名}/`(内部结构以 module-development-spec 为准) | | develop | 开发说明 | `repos/{项目名}_pc/docs/02-develop/dev-notes.md` | | test | 测试计划 / 用例 / 报告 | `repos/{项目名}_pc/docs/03-test/` | | deploy_test | 测试环境部署 | `repos/{项目名}_pc/docs/04-deploy/deploy-test-env.md` | @@ -125,7 +117,7 @@ QC/PM 检查交付件时,用 `read_file` / `list_files` 的路径是相对工 | 需求文档 | `repos/{项目名}_pc/docs/00-requirement/requirement-spec.md` | | 应用定义 | `repos/{项目名}_pc/apps/{应用名}.md` | | 设计文档 | `repos/{项目名}_pc/docs/01-design/` + `repos/{项目名}_pc/modules/` | -| 模块代码 | `repos/{模块名}/src/`、`repos/{模块名}/ddl/` | +| 模块代码 | `repos/{模块名}/`(内部结构以 module-development-spec 为准) | | 测试文档 | `repos/{项目名}_pc/docs/03-test/` | | 部署文档 | `repos/{项目名}_pc/docs/04-deploy/` | diff --git a/skills_library/pipelines/sdlc_general/roles/agent.develop/module-development/SKILL.md b/skills_library/pipelines/sdlc_general/roles/agent.develop/module-development/SKILL.md new file mode 100644 index 0000000..950775c --- /dev/null +++ b/skills_library/pipelines/sdlc_general/roles/agent.develop/module-development/SKILL.md @@ -0,0 +1,108 @@ +--- +name: module-development +description: 产线开发工程师模块开发规范——模块目录结构(包目录=模块名,非src)、init.py三处同步注册、表定义四段式/CRUD格式、RBAC load_path、模块技能文档、sqlor标准API(仅C/U/D/R/I/sqlExe)。触发:开发模块源码、创建模块仓库目录、写models/json/dspy/init.py。 +capability: task_capability +--- + +# 产线开发工程师模块开发规范 + +本 skill 是产线开发工程师(agent.develop)产出模块源码时必须遵守的规范。 +表定义四段式格式、CRUD 格式、sqlor API 的完整细则沿用 `module-development-spec` / `database-table-definition-spec` / `crud-definition-spec`, +本 skill 聚焦:**模块目录怎么建**、**init.py 怎么注册**、**表/CRUD 用什么格式**、**RBAC 怎么注册**、**模块技能文档怎么写**、**sqlor 只能用哪些 API**。 + +## 一、模块目录结构(铁律) + +每个模块一个独立仓库,仓库名 = 模块名(英文小写),目录结构: + +``` +{模块名}/ +├── {模块名}/ # Python 包目录(包名 = 模块名,不是 src/!) +│ ├── __init__.py # 导出 init.py 的 async 函数 +│ ├── init.py # load_{模块名}() 注册函数到 ServerEnv +│ └── *.py # 其他源码 +├── wwwroot/ # 前端 +│ ├── index.ui # 模块入口页(必须) +│ └── api/*.dspy # 后端接口 +├── models/ # 表定义 JSON(四段式) +├── json/ # CRUD 定义 JSON +├── init/ # 初始化数据 +│ └── data.json # 编码字典等种子数据 +├── scripts/ +│ └── load_path.py # RBAC 权限注册 +├── skill/ +│ └── SKILL.md # 模块技能文档(后续 agent 参考) +├── pyproject.toml # 打包配置 +└── README.md +``` + +**禁止**: +- 禁止用 `src/` 代替 `{模块名}/` 包目录——Python 包名必须 = 模块名,否则 `import {模块名}` 失败 +- 禁止把 `init.py`/`__init__.py` 放在模块根目录(必须在包目录 `{模块名}/` 内) +- 禁止用 `module.json` / `conf/rp.json` / `import_rp.py` 代替 `pyproject.toml` / `scripts/load_path.py` + +## 二、init.py 注册(三处同步,漏一处就 500) + +每个模块的 `init.py` 里必须有 `load_{模块名}()` 函数,把公开函数注册到 ServerEnv。 +**新增/删除一个函数必须同步改三处**: + +1. 函数定义(`{模块名}/init.py` 或包内其他 .py) +2. 导出(`{模块名}/__init__.py` 的 `from .init import (...)`) +3. 注册(`init.py` 的 `env.xxx = xxx`) + +漏 #2 → ImportError;漏 #3 → .dspy 里 NameError 500。 + +**CRUD 单复数**:xls2ui 生成的 CRUD wrapper dspy 用复数名(`create_xxx`),init.py 定义常是单数,两者都要注册: +```python +env.create_supplier = create_supplier +env.create_suppliers = create_supplier # xls2ui 用复数 +``` + +## 三、表定义四段式格式(models/*.json) + +每张表一个 JSON,格式 = `summary` + `fields` + `indexes` + `codes` 四段: + +```json +{ + "summary": [{"name": "org_employee", "title": "员工表", "primary": ["id"]}], + "fields": [ + {"name": "id", "title": "主键", "type": "str", "length": 32, "nullable": "no"}, + {"name": "orgid", "title": "所属组织", "type": "str", "length": 32}, + {"name": "empname", "title": "姓名", "type": "str", "length": 255}, + {"name": "salary", "title": "工资", "type": "double", "length": 18, "dec": 2}, + {"name": "status", "title": "状态", "type": "str", "length": 16}, + {"name": "created_at", "title": "创建时间", "type": "timestamp"} + ], + "indexes": [{"name": "idx_org_employee_org", "idxtype": "index", "idxfields": ["orgid"]}], + "codes": [{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='emp_status'"}] +} +``` + +**类型铁律**:用抽象类型 `str/int/double/timestamp/date/text`,**禁原生类型**(`varchar`/`bigint`/`boolean`/`int(11)`)。字段语义→类型映射见 design 角色技能 `database-design`。金额统一 `double` + `18/2`(用 double 不用 decimal)。业务日期用 `date` 不用 `timestamp`。 + +## 四、CRUD 定义格式(json/*.json) + +每个 CRUD 一个 JSON,根键 = `tblname` + `params`: + +```json +{"tblname": "org_employee", + "params": {"browserfields": {...}, "editable": {...}}} +``` + +**铁律**:根键必须是 `tblname` + `params`,不能自创 `{"table":..., "list":...}` 格式。 + +## 五、RBAC 权限注册(scripts/load_path.py) + +模块的 API/页面路径用 `scripts/load_path.py` 注册到 any/logined 角色(调 set_role_perm.py wrapper), +不用 `conf/rp.json` / `import_rp.py` 这种非标机制。 + +## 六、模块技能文档(skill/SKILL.md,必须) + +每个模块必须有 `skill/SKILL.md`,内容:数据模型(表清单+关键字段)、关键接口(dspy/函数)、陷阱、依赖。 +这是给后续 agent(测试/部署/维护)的参考,不能省。 + +## 七、sqlor 标准 API(禁编造) + +sqlor 只有这 6 个方法:`sor.C`(建) / `sor.U`(改) / `sor.D`(删) / `sor.R`(查) / `sor.I`(查表结构) / `sor.sqlExe`(原生SQL)。 +**禁止**编造 `sqlor.save/list/one/delete/insert/query` —— 这些不存在,会 NameError。 + +写原生 SQL 引用列名时,**必须核对 models/{表}.json 的字段名**,不要凭记忆猜(如 permission 表是 `path`/`name` 不是 `permcode`/`permname`)。