.cursor/skills/proto-backend-module/SKILL.md
Implements backend modules from proto definitions for goddess, marksman, and rabbit apps. Keeps style consistent with existing project structure, reuses magicbox and in-app code, follows Go and project conventions, and requires syncing README (API overview, features, usage) when adding, modifying, or removing modules or APIs. Use when the user says "帮我完成某某功能" or manually @ this skill to implement a module based on proto.
npx skillsauth add aide-family/moon proto-backend-moduleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
根据 proto 定义在 goddess、marksman、rabbit 中完成后端功能时,严格遵循本技能中的分层、命名和复用约定。
validateXxx、ensureYyy),由多处调用该函数,避免复制粘贴。这样后续修改校验或文案时只需改一处。proto/<app>/api/v1/*.proto,生成到 app/<app>/pkg/api/v1/*.pb.go(由 buf/kratos 生成,勿手改)。internal/conf/conf.proto 定义 Bootstrap;运行时配置(如 app/<app>/config/server.yaml)必须与 conf.proto 的字段同步,否则新增字段无法生效。修改 conf.proto 后必须同步修改实际使用的 YAML/配置文件。cmd/run/{http,grpc,job,all}/wire.go:wire 注入internal/conf:配置定义与生成internal/server:HTTP/gRPC 注册(RegisterHTTPService / RegisterGRPCService / RegisterService)internal/service:对接 proto 生成的 Server 接口,调 bizinternal/biz:业务逻辑;biz/repository 接口;biz/bo 请求/响应 BOinternal/data:data/impl 实现 repository;impl/do GORM 模型;impl/convert do↔bo 转换;impl/query 为 gorm gen 生成magicbox/ 下按包使用。实现新模块时,只在这些既有分层中新增或修改文件,不要新增顶层包或与现有命名风格不符的目录。
确认 proto 与生成代码
proto/<app>/api/v1/,go_package 指向 github.com/aide-family/<app>/pkg/api/v1。pkg/api/v1/*.pb.go(如未生成,提醒用户执行项目既定 make/buf 命令)。GET /v1/resource/{uid} 这类带路径参数的 route,不要新增 GET /v1/resource/xxx(会被匹配成 uid=xxx,导致解析错误)。应使用不同前缀或层级,例如 GET /v1/resources/xxx(复数前缀)、GET /v1/resource/action/xxx(多段),或单独资源名如 GET /v1/namespaces/simple。新增/修改 proto 的 google.api.http 后需执行 make api 并确认生成的路由表无冲突。make api/OpenAPI 生成会告警)。若需传递「要解除绑定的 ID 列表」等参数,不要使用 body: "*",应去掉 body,让 Request 中除路径变量外的字段通过 query 重复参数 传递(例如 DELETE /v1/notification-groups/{uid}/webhooks?webhook_uids=1&webhook_uids=2)。路径变量(如 {uid})照常写在 path 中。biz/bo
internal/biz/bo/ 下为当前模块增加类型(如 CreateXxxBo、UpdateXxxBo、XxxItemBo、ListXxxBo 等),与 proto 的 Request/Reply/Item 对应。*apiv1.*Request 构造 BO 的构造函数(如 NewCreateXxxBo(req *apiv1.CreateXxxRequest))。ToAPIV1XxxItem、ToAPIV1ListXxxReply)。PageRequestBo / PageResponseBo[T](见 biz/bo/page.go),不要新建分页类型。biz/repository
internal/biz/repository/ 下新增接口(如 XxxConfig),方法签名使用 context.Context、*bo.*Bo、snowflake.ID 等,返回业务所需类型(含 *bo.PageResponseBo[*bo.XxxItemBo] 等)。CreateXxxConfig、ListXxxConfig)。HasXxxData、HasYyyData),由 biz 组合逻辑,repo 只提供原子能力。data/impl/do
internal/data/impl/do/ 下新增 GORM 模型(嵌入 BaseModel,使用 snowflake.ID、gorm 标签、TableName())。strutil.EncryptString、safety.Map)。do.Models() 的返回切片,以便迁移与 gen。data/impl/convert
internal/data/impl/convert/ 下实现 do ↔ bo 的转换(如 ToXxxConfigDO、ToXxxConfigItemBo),使用 contextx.GetNamespace(ctx)、contextx.GetUserUID(ctx) 等填充创建人/命名空间。data/impl/query(gorm gen)
query.Xxx.WithContext(ctx).Where(...) 等调用。data/impl
internal/data/impl/ 下新增 xxx.go,实现 repository.XxxConfig:
NewXxxConfigRepository(d *data.Data) repository.XxxConfig,内部调用 query.SetDefault(d.DB())(若该 app 使用 SetDefault)。query.Xxx、convert.*、contextx.GetNamespace(ctx) 等实现,错误用 merr.ErrorNotFound / merr.ErrorInvalidArgument 等(与现有 impl 一致)。impl/provider_set.go 的 ProviderSetImpl 中注册 NewXxxConfigRepository。u.UserUID.Eq(x)、u.SortOrder.Desc()),禁止手写字符串条件(如 Where("user_uid = ?", ...)、Order("sort_order ASC"))。query.Xxx.WithContext(ctx).CreateInBatches(rows, len(rows)) 或一次 Create(rows...),禁止在 for 循环内逐条 Create。internal/biz
xxx_config.go(或与模块同名的 biz 文件),实现 NewXxxConfig(repo repository.XxxConfig, helper *klog.Helper) *XxxConfig,方法内调 repo、用 merr 和 helper.Errorw 处理错误与日志。biz/provider_set.go 的 ProviderSetBiz 中注册 NewXxxConfig。internal/service
xxx.go,实现 proto 生成的 XxxServer 接口(嵌入 apiv1.UnimplementedXxxServer),各 RPC 方法:将 *apiv1.*Request 转为 bo、调 biz、将 bo 转为 *apiv1.*Reply。service/provider_set.go 的 ProviderSetService 中注册 NewXxxService。internal/server
RegisterHTTPService / RegisterGRPCService(以及如需全量的 RegisterService)中增加对新 service 的依赖参数,并调用 apiv1.RegisterXxxHTTPServer / apiv1.RegisterXxxServer。namespaceAllowList 或 authAllowList 中加上对应 Operation 常量。authAllowList 或 namespaceAllowList,否则中间件会拦截导致接口不可用。wire
wire ./cmd/run/... 等以更新注入;否则在对应 wire.go 中确保 server、service、biz、impl、data 的 ProviderSet 已包含新模块。配置与 conf.proto 同步
internal/conf/conf.proto(如在 Bootstrap 中新增、删除或重命名字段),必须同步修改该应用实际使用的运行时配置文件(如 app/<app>/config/server.yaml 或 config/*.yaml),为新增字段补充对应配置项,否则启动时可能缺省或报错。selfDomain、userDomain);领域模块配置统一使用「领域名称+Domain」(如 namespaceDomain、webhookDomain);认证/登录领域使用 authDomain(不用 loginDomain,以保持命名专业性);结构需与 magicbox 或现有同类型配置一致(如 DomainConfig 的 driver、version、options)。README 与文档同步
README.md 与 README-zh_CN.md,结构和表格一一对应。以下约定来自实践中的中途修正,实现时请直接遵守,避免返工。
若业务约定「SortOrder 数值越大越靠前」(列表第一项展示时排最前):
slices.Clone + slices.Reverse 反转后再按索引赋 SortOrder(反转后遍历,索引 0 对应原列表最后一项、会得到最小 SortOrder,原列表第一项会得到最大 SortOrder);或显式 SortOrder: int32(n-1-i)。Order(field.SortOrder.Desc()),保证大的先返回。避免手写「n-1-i」时搞反顺序;用 slices.Reverse 时语义更直观。
当需要校验「一批 ID 是否都存在 / 是否都在当前命名空间」时:
CountXxxByUIDs(ctx, uids []snowflake.ID) (int64, error)),在 impl 内用 Where(..., ID.In(uidInt64s...)).Count() 一次查询。count == len(uids) 即可,禁止在 for 循环内逐条调用 GetXxx(ctx, id) 做校验。当需要根据一批 UID 拉取详情列表并保持与输入一致的顺序时:
GetXxxByUIDs(ctx, uids []snowflake.ID) ([]*bo.XxxItemBo, error)),在 impl 内用 Where(..., ID.In(...)).Find() 一次查询。map[uid]*bo,再按原始 uids 顺序遍历,从 map 中取并 append,得到有序结果;禁止在 for 循环内逐条 GetXxx(ctx, uid)。为保证项目质量,对 proto/模块/功能做任何变更时,必须同步维护 README,避免文档与实现脱节。
| 变更类型 | 需更新的配置 | 更新内容 |
|----------|--------------|----------|
| conf.proto 新增 Bootstrap 字段 | 该应用实际使用的配置文件(如 app/<app>/config/server.yaml) | 在 YAML 中新增与字段名一致的配置项(如 selfDomain、userDomain),结构参考同类型已有配置(如 namespaceDomain) |
| conf.proto 删除/重命名 字段 | 同上 | 从配置文件中删除或重命名对应项,避免遗留无效配置 |
说明:仅改 conf.proto 并执行 make conf 生成 conf.pb.go 不够,运行时加载的是 YAML 等配置文件;若不同步修改配置文件,新字段在运行时为 nil 或零值,依赖该配置的模块可能报错(如 "selfDomain is required")。
| 变更类型 | 需更新的 README | 更新内容 |
|----------|-----------------|----------|
| 新增 RPC / Service / 模块 | 该应用下的 README.md与 README-zh_CN.md(二者都改) | Features:补充一条新能力描述;API Overview 表:补充新接口/新服务;必要时补充常用用法 |
| 修改 RPC 路径、方法名、请求/响应语义 | 同上 | API Overview 表:修正 HTTP 路径、方法描述;若影响功能描述则同步更新 Features |
| 删除 RPC / Service / 模块 | 同上 | 从 Features、API Overview 表中移除对应项;若整模块删除则从接口概览整块移除 |
| 新增/删除/重命名应用(如新 app) | 仓库根目录 README.md、README-zh_CN.md | Project Structure 表、Documentation 表、Quick Start 中应用列表 |
| magicbox 新增/删除/重命名包或对外能力 | magicbox/README.md、magicbox/README-zh_CN.md | Module Overview 表、Features;若新增 proto 则更新 Proto 定义表 |
README.md、README-zh_CN.md(项目结构、各应用入口、文档链接)app/goddess/README.md、app/goddess/README-zh_CN.mdapp/rabbit/README.md、app/rabbit/README-zh_CN.mdapp/marksman/README.md、app/marksman/README-zh_CN.mdmagicbox/README.md、magicbox/README-zh_CN.mdREADME.md 与 README-zh_CN.md,结构和表格一一对应,仅语言不同。只改中文或只改英文视为未完成。proto/<app>/api/v1/*.proto 与 google.api.http 注解。完成模块实现或 proto 变更后,在自检时必须勾选「README 已同步」,并确认:Features 已更新、API Overview 已更新、README.md 与 README-zh_CN.md 均已更新。
helper.Errorw("msg", "…")), error strings (e.g. merr.ErrorNotFound("…")), and any other user-facing or developer-facing text. No Chinese or mixed language in code. Follow Effective Go and standard Go style (concise, clear, consistent). Multi-language UX is handled by frontend/i18n using error codes or keys; the backend exposes stable English messages only._ "...")github.com/aide-family/<app>/...)CreateXxx)。*_test.go),与现有 magicbox 和 app 内测试风格一致。biz/bo/page.go 的 PageRequestBo、PageResponseBo[T]slices.Clone、slices.Reverse(用于按「越大越靠前」赋 SortOrder 等)magicbox/merr(如 ErrorNotFound、ErrorInvalidArgument、ErrorParams、IsNotFound)magicbox/contextx(如 GetNamespace、GetUserUID)magicbox/enum(与 proto 一致)magicbox/strutil.EncryptString、magicbox/safety.Mapklog.Helper 的 Errorw 等,与现有 biz 一致github.com/bwmarrin/snowflake,snowflake.ParseInt64、uid.Int64()domain/<domain>/v1/ 的领域注册(如 namespace、user),新领域实现需在对应 domain/xxx/v1/ 下实现并注册;若只是扩展现有 API,在 internal/service 与 internal/biz 中按上述流程即可。goddessv1 "github.com/aide-family/goddess/pkg/api/v1"),仅引用已有客户端与接口,不新建 goddess 端未定义的包。pkg/api/v1,未手改生成代码internal/conf/conf.proto,已执行 make conf(或项目约定的 conf 生成命令),并已同步修改该应用实际使用的配置文件(如 config/server.yaml),为新增/变更的 Bootstrap 字段补充对应配置项;认证/登录领域配置使用 authDomain(勿用 loginDomain)authAllowList 或 namespaceAllowList/resource/{id} 时,勿用 /resource/word,改用 /resources/word 等)u.UserUID.Eq(...)、u.SortOrder.Desc()),未使用手写字符串;批量插入使用 CreateInBatches 或一次 Create(slice),未在循环内逐条 Createquery.Xxx.WithContext(ctx) 完成,未直接使用原生 GORM Model/Where/First/Find/Create/Save/Delete 链式调用README.md 与 README-zh_CN.md;且 功能特性(Features) 与 接口概览(API Overview)表 均已补充/修改/删除对应内容,中英文一一对应,与当前 proto 一致更多分层与文件命名细节见 reference.md。
以下规则来自实际返工点,默认同样强制执行。
ctx 外超过 2 个参数必须收敛为结构体context.Context 外,其余参数若超过 2 个,必须封装到一个 *bo.XxxInput / *bo.XxxRepoBo 结构体中,不允许长参数列表。XxxInput、SubmitXxxInput、ExecuteXxxBoXxxRepoBo、UpdateXxxRepoBo、CountXxxRepoBomagicbox/enumproto/magicbox/enum/enum.proto,并在业务 proto 中 import "magicbox/enum/enum.proto" 后引用。int32 常量模拟枚举语义。proto/magicbox/enum/enum.protomagicbox/enum/*.pb.go(cd magicbox && make proto)cd app/<app> && make api)magicbox/README.md 与 magicbox/README-zh_CN.md 的 enum 说明。UpdateColumnSimpleUpdateColumnSimple(columns...) + []field.AssignExpr。internal/data/impl/query 的 gen 对象完成(如 query.Xxx.WithContext(ctx))。r.DB().WithContext(ctx).Model(...).Where(...).First/Find/Create/Save/Delete/Count 这类原生 GORM 链式调用。Updates(map[string]interface{}{...})(字符串列名)columns := []field.AssignExpr{ q.FieldA.Value(v), q.FieldB.Value(v2) }..., err := q.WithContext(ctx).Where(...).UpdateColumnSimple(columns...)BO -> APIV1 转换函数放在 internal/biz/bo/(如 ToAPIV1XxxItem)。DO <-> BO 转换函数放在 internal/data/impl/convert/。convert,避免散落在 impl。toXxxItemBo 这类 DO->BO 映射辅助函数,不允许留在 internal/data/impl/*.go,必须统一放到 internal/data/impl/convert/*.go。message 字段名必须是 camelCase。snake_case 字段名(如 work_dir, page_size, status_filter)。{commandUid} 对应 commandUid)。timexmagicbox/timex(如 timex.FormatTime),不要在业务代码里散落 time.RFC3339 手动格式化。CreatedAt: timex.FormatTime(&x.CreatedAt)ReviewedAt: timex.FormatTime(x.ReviewedAt)A -> B -> C 的无意义包裹。ToPlainEnv / ToSafetyEnv)development
Reviews code for correctness and potential bugs, pinpoints bug locations by file and line, and suggests concrete fixes. Use when the user asks for a code review, wants to find bugs, or mentions reviewing code or changes.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.