| name | update-openapi-registry |
| description | 处理 zentao-api 的 OpenAPI 与模块注册库更新:比较 operation 契约和示例变化,维护 zentao-api-map.json 的模块、action 名称及 ModuleAction 属性映射,解决命名冲突,核对 GET resultGetter,审计每个非 Token operation 的直接或合并覆盖,并重新生成验证 src/modules/generated.ts。用户提出更新 OpenAPI、同步注册库、重新生成模块定义、处理 action 冲突或结果字段、检查 zentao-openapi.json 差异及报告接口变化时使用。 |
更新 OpenAPI 注册库
从 zentao-api 仓库根目录执行流程,遵守项目 AGENTS.md,只使用 Bun 运行项目脚本。保留用户已有改动;默认不暂存、提交、推送、发布或生成文档,除非用户明确要求。
1. 确认范围和状态
- 运行
git rev-parse --show-toplevel,确认仓库根目录。
- 运行
git status --short --branch,区分用户已有改动和本次生成结果。
- 确认
data/zentao-openapi.json 的比较基线:
- 工作区或暂存区更新通常与
HEAD 比较。
- 更新已经提交时,使用用户指定的 ref;没有指定时检查提交历史后选择明确的基线,不要盲目假设
HEAD^。
- 不覆盖、还原或重新格式化用户提供的 OpenAPI 文件。
2. 生成结构化差异报告
运行技能脚本:
bun run .agents/skills/update-openapi-registry/scripts/report-openapi-changes.ts --base HEAD
需要机器可读结果时追加 --json。脚本将 operation 分为新增、删除、契约或元数据变化、仅示例变化。以结构化结果为准,不根据 JSON 文本行数判断接口数量。
重点检查:
- HTTP method、path、参数位置、类型、必填项、默认值和枚举。
- request body 的 media type、schema 和 required。
- response schema、分页字段和结果容器。
components.schemas 等共享定义;共享 component 变化时继续追踪引用它的 operation,不能只看 path 本身。
- 只有
example 或 examples 变化时,明确标为示例刷新,不宣称接口契约改变。
3. 处理 action 映射与命名冲突
自动分类不能准确表达接口语义,或同一模块出现重名 action 时,维护 scripts/zentao-api-map.json。键必须是规范化的 <小写 method> <OpenAPI path>,路径参数使用 {paramName}。值是对推断结果的部分覆盖:
{
"get /tasks/{taskID}": {"resultGetter": "task"},
"post /projects/{projectID}/stories": {"module": "project", "name": "createStory"}
}
operation 完整性硬约束
- 除
Token tag 的登录类 operation 外,每个 OpenAPI operation 都必须有可核对的最终归宿:生成一个独立 action,或合并进一个实际包含该 scope 的 scoped-list action。不得因为 action 重名、已有顶层 list、自动分类失败或生成器限制而跳过、覆盖或静默丢弃 operation。
- 同一最终模块同时存在顶层
list 和 scoped-list 时,不能只保留顶层 list,也不能自动把 scoped-list 视为已覆盖。必须逐项在 scripts/zentao-api-map.json 中提供语义化 name,使其作为独立 action 生成。例如:
{
"get /programs/{programID}/products": {"name": "programProducts"}
}
- 如果多个 scoped operation 可以安全合并,必须能从最终 action 的
scope options 逐项反查每个来源 operation;父级资源或子资源语义不同而无法证明等价时,改用手动 name 映射,不能强行合并。
- 如果暂时无法确定语义化名称,停止在映射阶段并报告待确认项;不得交付部分生成结果。
遵守以下规则:
module、name 都是可选字段;省略时保留 OpenAPI tag 和自动分类得到的值。其他字段直接覆盖对应的 ModuleAction 属性。
ModuleAction.name 只保存 action 部分,例如 team、createStory,不能写成 project-team。用于报告或外部标识的完整名称严格写成 <moduleName>-<actionName>,例如 project-team、project-createStory。
- 多单词 action 使用 camelCase,不能用额外的
- 连接。根据接口实际语义命名,例如 my-todos、my-tasks,不要使用 list2 一类无语义后缀。
module 或 name 属于结构映射;仅设置 resultGetter 等属性时,不得改变原有模块、action 名称或 scoped-list 合并行为。
- 多个 scoped operation 合并为一个 action 时,同一属性的映射值必须一致;不一致时应报出冲突,不能按遍历顺序静默覆盖。
- 生成器应处理完全部 operation 后,按最终 module/action 分组,一次性列出所有未解决的重名、对应 method/path 和映射状态。不要只修复第一个冲突。
每轮映射后重新生成并运行 operation 覆盖审计,阅读完整提示;仍有冲突或未覆盖 operation 时继续补充映射,不要把有冲突或覆盖不完整的生成结果当作完成。
4. 重新生成注册库
运行:
bun run scripts/update-registry.ts
git diff -- src/modules/generated.ts
bun run .agents/skills/update-openapi-registry/scripts/audit-generated-registry.ts
覆盖审计必须报告 uncovered: 0。如果它报告“模块已有顶层 list 的 unmapped scoped list”,在 scripts/zentao-api-map.json 为每个接口补充语义化 name,重新生成并重复审计。registry:check 输出的 operation 数量是生成器输入数量,不能单独证明 operation 已进入最终注册表。
不要手工修改 src/modules/generated.ts。如果生成结果错误:
- OpenAPI 可以表达正确含义时,修正 OpenAPI 或通用生成器,并添加回归测试。
- 静态的 module、action 名称或
ModuleAction 属性差异,优先写入 scripts/zentao-api-map.json。
- 只有映射无法表达函数或运行时行为时,才在
src/modules/override.ts 添加最小内置覆盖,并用测试证明必要性。
- 检查新增 action 是否同步进入
BuiltinActionMeta,GET action 是否保留正确的 resultGetter / pagerGetter。
- 检查说明文本中的嵌套中英文括号是否仍能解析默认值和 options。
- 检查
file/create 最终注册定义仍包含 multipart/form-data 和二进制文件字段;运行上传测试确认实际请求没有退化为 JSON。
修改生成器或 override 时,只处理由当前 OpenAPI 更新暴露的问题,不顺手重构无关代码。
5. 确认 GET 结果字段
所有生成的 GET action 都必须具有非空 resultGetter。按以下证据顺序确定字段:
- 优先读取
200 application/json response schema 中除 status、pager 等元数据外的结果容器。
- schema 缺失或与 example 不一致时检查 response example,但不要把示例数据值当作契约。
- 用户明确提供或授权测试环境时,只执行 GET:从 OpenAPI 生成必需路径和查询参数,通过父级列表接口取得有效 ID,再请求目标接口。只输出顶层字段名和类型,不打印业务数据,不把 token 写入仓库、日志或报告。
- 测试接口不可用时,查找权威服务端路由或正式文档中的 response extractor;明确标记推断依据和剩余风险,不能把 HTML 错误页当作响应契约。
OpenAPI 无法推断出的字段写入映射,例如 {"resultGetter": "task"}。列表接口只有实际响应包含分页容器时才设置 pagerGetter。
6. 验证
先运行针对性检查,再运行完整检查:
bun run .agents/skills/update-openapi-registry/scripts/audit-generated-registry.ts
bun run registry:check
bun run typecheck
bun run check
git diff --check
根据变更补充针对性测试,例如:
bun test tests/upload.test.ts tests/modules.test.ts tests/resolve.test.ts
映射或生成器变化至少覆盖这些回归断言:
- 映射可以只提供
resultGetter 等属性,不强制要求 module 和 name。
- 映射根据 method/path 找到最终 action,并逐项应用覆盖属性。
- 每个模块内 action 名称唯一,所有生成 GET action 都有非空
resultGetter。
- scoped-list 的纯属性映射不会改变原有 path、display、pathParams 或合并范围。
- 每个非 Token OpenAPI operation 都被一个独立 action 直接覆盖,或被 scope options 明确包含的 scoped-list action 合并覆盖;未覆盖数量必须为 0。
- 同一模块同时存在顶层
list 和未命名 scoped-list 时,审计必须失败并要求通过 zentao-api-map.json 配置语义化 name。
- operation 缺少 tag、合并组包含不同子资源,或映射后的 action 无法在
generated.ts 中找到时,审计必须失败,不能将其计为已处理。
bun run check 不包含真实环境测试。只有用户要求且环境配置可用时运行 bun run test:real;否则在报告中明确未运行。
7. 复核和报告
再次运行 git status --short --branch 和 git diff --stat,确认没有意外文件。报告至少包含:
- 当前模块和 operation 数量、共享 component 变化,以及是否有接口删除。
- 新增接口:method、path、SDK action 名、主要入参和结果类型。
- 现有接口变更:按请求契约、查询参数、响应契约和说明变化分组。
- 仅示例变化的数量,不必逐项展开无业务影响的时间戳、token 或测试数据刷新。
- 为保持运行时兼容而修改的生成器、override 和测试。
- 实际执行的验证、通过数量、未执行的真实环境验证和剩余风险。
- 新增或调整的 API 映射、最终
<moduleName>-<actionName>、未解决冲突数量。
- GET action 总数、缺失
resultGetter 数量,以及真实请求确认和推断确认的范围。
- 非 Token operation 总数、独立 action 覆盖数量、合并覆盖数量、未覆盖数量;未覆盖数量不为 0 时不得报告完成。
- 被合并的 operation 到 scoped-list action 的对应关系,以及因顶层
list 冲突而新增的手动映射。
不要把生成器输出数量与 SDK action 数量混为一谈,也不要把生成器打印的 operation 数量当作覆盖证明:多个 scoped OpenAPI operation 可以合并为一个注册 action,Token 类 operation 可以被生成器排除,但任何非 Token operation 都不能没有可验证的最终归宿。