cgraphx 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/.claude-template/hooks/precommit-check/precommit-check.cjs +90 -0
  2. package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +99 -78
  3. package/dist/.claude-template/skills/precommit-review/SKILL.md +50 -0
  4. package/dist/.claude-template/skills/run-api-test/SKILL.md +187 -0
  5. package/dist/.claude-template/skills/run-api-test/assets/template-test-report.md +103 -0
  6. package/dist/.claude-template/skills/run-api-test/assets/template-test-verify.jsonl +5 -0
  7. package/dist/.claude-template/skills/run-api-test/references/bru-run.md +60 -0
  8. package/dist/.claude-template/skills/run-api-test/references/db-verification.md +81 -0
  9. package/dist/.claude-template/skills/run-api-test/references/report-format.md +104 -0
  10. package/dist/.claude-template/skills/run-api-test/references/service-readiness.md +61 -0
  11. package/dist/.claude-template/skills/run-api-test/references/test-scope.md +64 -0
  12. package/dist/.claude-template/skills/write-api/SKILL.md +150 -0
  13. package/dist/.claude-template/skills/write-api/assets/template-api-spec.md +112 -0
  14. package/dist/.claude-template/skills/write-api/assets/template-request.bru +75 -0
  15. package/dist/.claude-template/skills/write-api/references/ai-prompts.md +133 -0
  16. package/dist/.claude-template/skills/write-api/references/api-spec-format.md +108 -0
  17. package/dist/.claude-template/skills/write-api/references/bru-format.md +144 -0
  18. package/dist/.claude-template/skills/write-api/references/collection-layout.md +81 -0
  19. package/dist/.claude-template/skills/write-api/references/environment-setup.md +105 -0
  20. package/dist/.claude-template/skills/write-api/references/interface-scope.md +74 -0
  21. package/dist/api-test/ai-fields.d.ts +37 -0
  22. package/dist/api-test/ai-fields.d.ts.map +1 -0
  23. package/dist/api-test/ai-fields.js +114 -0
  24. package/dist/api-test/ai-fields.js.map +1 -0
  25. package/dist/api-test/assemble.d.ts +76 -0
  26. package/dist/api-test/assemble.d.ts.map +1 -0
  27. package/dist/api-test/assemble.js +185 -0
  28. package/dist/api-test/assemble.js.map +1 -0
  29. package/dist/api-test/bru-cli-invoker.d.ts +72 -0
  30. package/dist/api-test/bru-cli-invoker.d.ts.map +1 -0
  31. package/dist/api-test/bru-cli-invoker.js +169 -0
  32. package/dist/api-test/bru-cli-invoker.js.map +1 -0
  33. package/dist/api-test/bru-report-parser.d.ts +24 -0
  34. package/dist/api-test/bru-report-parser.d.ts.map +1 -0
  35. package/dist/api-test/bru-report-parser.js +110 -0
  36. package/dist/api-test/bru-report-parser.js.map +1 -0
  37. package/dist/api-test/bru-runner.d.ts +101 -0
  38. package/dist/api-test/bru-runner.d.ts.map +1 -0
  39. package/dist/api-test/bru-runner.js +316 -0
  40. package/dist/api-test/bru-runner.js.map +1 -0
  41. package/dist/api-test/bru-writer.d.ts +52 -0
  42. package/dist/api-test/bru-writer.d.ts.map +1 -0
  43. package/dist/api-test/bru-writer.js +159 -0
  44. package/dist/api-test/bru-writer.js.map +1 -0
  45. package/dist/api-test/call-chain-extractor.d.ts +80 -0
  46. package/dist/api-test/call-chain-extractor.d.ts.map +1 -0
  47. package/dist/api-test/call-chain-extractor.js +179 -0
  48. package/dist/api-test/call-chain-extractor.js.map +1 -0
  49. package/dist/api-test/cli.d.ts +133 -0
  50. package/dist/api-test/cli.d.ts.map +1 -0
  51. package/dist/api-test/cli.js +1009 -0
  52. package/dist/api-test/cli.js.map +1 -0
  53. package/dist/api-test/config.d.ts +75 -0
  54. package/dist/api-test/config.d.ts.map +1 -0
  55. package/dist/api-test/config.js +406 -0
  56. package/dist/api-test/config.js.map +1 -0
  57. package/dist/api-test/db-query-cli.d.ts +51 -0
  58. package/dist/api-test/db-query-cli.d.ts.map +1 -0
  59. package/dist/api-test/db-query-cli.js +119 -0
  60. package/dist/api-test/db-query-cli.js.map +1 -0
  61. package/dist/api-test/enhance-prepare.d.ts +111 -0
  62. package/dist/api-test/enhance-prepare.d.ts.map +1 -0
  63. package/dist/api-test/enhance-prepare.js +425 -0
  64. package/dist/api-test/enhance-prepare.js.map +1 -0
  65. package/dist/api-test/enhance-write.d.ts +28 -0
  66. package/dist/api-test/enhance-write.d.ts.map +1 -0
  67. package/dist/api-test/enhance-write.js +145 -0
  68. package/dist/api-test/enhance-write.js.map +1 -0
  69. package/dist/api-test/errors.d.ts +48 -0
  70. package/dist/api-test/errors.d.ts.map +1 -0
  71. package/dist/api-test/errors.js +76 -0
  72. package/dist/api-test/errors.js.map +1 -0
  73. package/dist/api-test/field-extractor.d.ts +98 -0
  74. package/dist/api-test/field-extractor.d.ts.map +1 -0
  75. package/dist/api-test/field-extractor.js +327 -0
  76. package/dist/api-test/field-extractor.js.map +1 -0
  77. package/dist/api-test/impl-finder.d.ts +37 -0
  78. package/dist/api-test/impl-finder.d.ts.map +1 -0
  79. package/dist/api-test/impl-finder.js +54 -0
  80. package/dist/api-test/impl-finder.js.map +1 -0
  81. package/dist/api-test/index.d.ts +41 -0
  82. package/dist/api-test/index.d.ts.map +1 -0
  83. package/dist/api-test/index.js +124 -0
  84. package/dist/api-test/index.js.map +1 -0
  85. package/dist/api-test/java-parser.d.ts +89 -0
  86. package/dist/api-test/java-parser.d.ts.map +1 -0
  87. package/dist/api-test/java-parser.js +508 -0
  88. package/dist/api-test/java-parser.js.map +1 -0
  89. package/dist/api-test/md-writer.d.ts +49 -0
  90. package/dist/api-test/md-writer.d.ts.map +1 -0
  91. package/dist/api-test/md-writer.js +202 -0
  92. package/dist/api-test/md-writer.js.map +1 -0
  93. package/dist/api-test/parser-httpservice.d.ts +91 -0
  94. package/dist/api-test/parser-httpservice.d.ts.map +1 -0
  95. package/dist/api-test/parser-httpservice.js +271 -0
  96. package/dist/api-test/parser-httpservice.js.map +1 -0
  97. package/dist/api-test/report.d.ts +188 -0
  98. package/dist/api-test/report.d.ts.map +1 -0
  99. package/dist/api-test/report.js +522 -0
  100. package/dist/api-test/report.js.map +1 -0
  101. package/dist/api-test/snapshot.d.ts +26 -0
  102. package/dist/api-test/snapshot.d.ts.map +1 -0
  103. package/dist/api-test/snapshot.js +150 -0
  104. package/dist/api-test/snapshot.js.map +1 -0
  105. package/dist/api-test/test-history.d.ts +48 -0
  106. package/dist/api-test/test-history.d.ts.map +1 -0
  107. package/dist/api-test/test-history.js +122 -0
  108. package/dist/api-test/test-history.js.map +1 -0
  109. package/dist/api-test/types.d.ts +174 -0
  110. package/dist/api-test/types.d.ts.map +1 -0
  111. package/dist/api-test/types.js +13 -0
  112. package/dist/api-test/types.js.map +1 -0
  113. package/dist/api-test/verify-prepare.d.ts +30 -0
  114. package/dist/api-test/verify-prepare.d.ts.map +1 -0
  115. package/dist/api-test/verify-prepare.js +150 -0
  116. package/dist/api-test/verify-prepare.js.map +1 -0
  117. package/dist/api-test/verify-write.d.ts +31 -0
  118. package/dist/api-test/verify-write.d.ts.map +1 -0
  119. package/dist/api-test/verify-write.js +159 -0
  120. package/dist/api-test/verify-write.js.map +1 -0
  121. package/dist/dbquery/dump-schema.d.ts +46 -0
  122. package/dist/dbquery/dump-schema.d.ts.map +1 -0
  123. package/dist/dbquery/dump-schema.js +379 -0
  124. package/dist/dbquery/dump-schema.js.map +1 -0
  125. package/dist/installer/targets/claude.d.ts +15 -0
  126. package/dist/installer/targets/claude.d.ts.map +1 -1
  127. package/dist/installer/targets/claude.js +53 -0
  128. package/dist/installer/targets/claude.js.map +1 -1
  129. package/package.json +1 -1
  130. package/scripts/agent-eval/block-cgraphx-and-gitnexus-cli-hook.sh +0 -43
  131. package/scripts/agent-eval/block-cgraphx-cli-hook.sh +0 -32
  132. package/scripts/agent-eval/block-cgraphx-cli-settings.json +0 -16
  133. package/scripts/agent-eval/cli-vs-mcp-3arm.sh +0 -121
  134. package/scripts/agent-eval/multi-tool-eval.sh +0 -171
  135. package/scripts/agent-eval/parse-cli-vs-mcp.mjs +0 -232
  136. package/scripts/agent-eval/parse-multi-tool.mjs +0 -242
@@ -0,0 +1,75 @@
1
+ meta {
2
+ name: <场景名,如 正常 / 缺prodInstId / 产品不存在>
3
+ type: http
4
+ }
5
+
6
+ # HTTP 方法段:get / post / put / delete / patch
7
+ # 查询接口示例(get):
8
+ get {
9
+ url: {{baseUrl}}/api/v1/users/:id
10
+ body: none
11
+ }
12
+
13
+ # 写接口示例(post,取消注释切换):
14
+ # post {
15
+ # url: {{baseUrl}}/api/v1/users
16
+ # body: json
17
+ # }
18
+
19
+ params:query {
20
+ # 查询参数,写真实值(AI 从 DB 查或代码推断),不变量化
21
+ # expand: true
22
+ # ~disabled_param: value # ~ 前缀表示禁用此参数
23
+ }
24
+
25
+ params:path {
26
+ # 路径参数,写真实值(如 id: 12345),不变量化
27
+ # 唯一例外:前置接口动态传递的值可用 {{var}}
28
+ # id: {{test_user_id}}
29
+ id: 12345
30
+ }
31
+
32
+ headers {
33
+ Content-Type: application/json
34
+ # 鉴权 header 由 AI 在 S3 根据项目既有 .bru 和 environments/local.bru 的变量名对齐后追加
35
+ # 不同项目鉴权方式不同(accesstoken/staffcode/regionid 或 Authorization/X-API-Key 等)
36
+ # 不在此硬编码示例,避免 AI 套模板;AI 必须按目标项目实际生成
37
+ }
38
+
39
+ # 请求体(写接口用,查询接口删此段):
40
+ # 入参写真实值(AI 从 DB 查或代码推断),不变量化
41
+ # 唯一例外:前置接口动态传递的值可用 {{var}}
42
+ # body:json {
43
+ # {
44
+ # "name": "测试用户",
45
+ # "email": "test@example.com",
46
+ # "phone": "13800000000"
47
+ # }
48
+ # }
49
+
50
+ # 测试脚本:用项目既有 bruno 版本支持的语法
51
+ # 既有语法:test("name", function() { ... }) + res.getStatus() / res.getBody()
52
+ # 不要用 function onResponse(request, response) 新语法
53
+ # 不要用 assert 段(项目 bruno 版本可能不支持),断言全放 tests
54
+ tests {
55
+ test("HTTP 200", function() {
56
+ expect(res.getStatus()).to.equal(200);
57
+ });
58
+
59
+ test("响应体关键字段", function() {
60
+ const body = JSON.parse(res.getBody());
61
+ expect(body.code).to.equal(0);
62
+ expect(body.data).to.exist;
63
+ });
64
+
65
+ # 写接口额外写 DB 副作用预期注释,供 S6 AI 核实参考:
66
+ # DB 预期:users 表新增一行,name=测试用户,email=test@example.com
67
+ # DB 预期:user_profile 表同步新增一行,user_id=本次返回的 id
68
+ }
69
+
70
+ docs {
71
+ 业务说明: <一句话,从 Javadoc 或 spec 提取;提取不到占位"(scan 阶段未提取到 Javadoc,请补充业务说明)">
72
+
73
+ 关联需求:
74
+ - <YYYY-MM-DD-feature-id> (<文件前缀>-spec.md)
75
+ }
@@ -0,0 +1,133 @@
1
+ # AI Prompt 指引(S2 + S3)
2
+
3
+ ## S2 微服务识别 prompt 指引
4
+
5
+ ### 输入
6
+
7
+ AI 在 S2 生成测试规格时,先读以下上下文:
8
+ - 项目结构:顶层目录、`package.json` / `pom.xml` / `go.mod` 等包描述
9
+ - `docs/bruno/` 既有子目录(避免命名漂移)
10
+ - 本次接口清单(S1 拿到)
11
+ - 接口路径前缀
12
+
13
+ ### 判断
14
+
15
+ AI 判定每个接口归属的服务名,或判定为"无服务划分"。
16
+
17
+ 判断依据:
18
+ - 项目根有 `services/` / `apps/` / `packages/` 等多模块目录 → 每个一级子目录视为一个服务,子目录名作服务名
19
+ - 接口路径前缀含服务名标识(如 `/so-assist-service/openapi/xxx`)→ 取路径段作服务名
20
+ - 单体项目无明显服务边界 → 判定为"无服务划分"
21
+
22
+ ### 跨 feature 一致性
23
+
24
+ AI 识别时**优先参考 `docs/bruno/` 既有服务目录名**,避免同一服务在不同 feature 间命名漂移。
25
+
26
+ 例:既有 `docs/bruno/so-assist-service/`,新接口也属该服务,就用 `so-assist-service`,不新取 `so-assist`。
27
+
28
+ ### 输出
29
+
30
+ 结果写入测试规格 §1 接口清单的"服务"列:
31
+ - 有服务归属 → 填服务名
32
+ - 无服务划分 → 填 `-` 或 `(无)`
33
+
34
+ 用户可在 S3 前手动校正此列。
35
+
36
+ ---
37
+
38
+ ## S2 通用接口判断 prompt 指引
39
+
40
+ ### 输入
41
+
42
+ AI 在 S2 判断每个接口是否通用时,读:
43
+ - 接口路径
44
+ - 接口语义(从代码或 spec 拿)
45
+ - `docs/bruno/common/` 既有接口(避免重复生成)
46
+
47
+ ### 判断
48
+
49
+ AI 判定是否"通用接口"——跨 feature 复用的前置接口归为通用:
50
+
51
+ | 类型 | 例 |
52
+ |---|---|
53
+ | 登录 / token 刷新 | `/auth/login`、`/auth/refresh` |
54
+ | 健康检查 | `/health`、`/healthcheck`、`/actuator/health` |
55
+ | 公共字典 | `/common/dict`、`/common/enum` |
56
+ | 公共枚举 | 系统级枚举查询 |
57
+
58
+ ### 跨 feature 一致性
59
+
60
+ AI 判断时**优先参考 `docs/bruno/common/` 既有接口**,避免重复生成。
61
+
62
+ 例:`common/login/` 已存在,新 feature 的登录接口不重复生成,直接复用。
63
+
64
+ ### 输出
65
+
66
+ 结果写入测试规格 §1 接口清单的"通用"列:`yes` / `no`。
67
+
68
+ `yes` 的接口,S3 落盘时归 `docs/bruno/common/<接口名>/`,不绑 feature。
69
+
70
+ 用户可在 S3 前手动校正此列。
71
+
72
+ ---
73
+
74
+ ## S3 生成 .bru prompt 指引
75
+
76
+ ### 单次调用约束
77
+
78
+ **单次 AI 调用生成全部 .bru**——不拆两阶段(先程序化骨架后 AI 增强),不逐接口循环。
79
+
80
+ 理由:
81
+ - 拆两阶段会让 AI 在第二阶段重新读一遍上下文,浪费 token
82
+ - 逐接口循环在接口多时上下文丢失,生成质量下降
83
+ - 单次调用让 AI 看全局,断言一致性更好
84
+
85
+ ### 输入
86
+
87
+ - 接口清单(S1)
88
+ - 测试规格文档(S2 产出)
89
+ - 代码上下文:通过 `codegraph_explore` 拿 handler 源码、参数定义、默认值、必填项
90
+ - DB 数据:通过 `db-query` 查真实可用数据
91
+
92
+ ### 输出
93
+
94
+ 每个接口的**每个场景**一个 `.bru` 文件,符合 `bru-format.md` 规范:
95
+ - `meta { name, type: http }`
96
+ - HTTP 方法段 + `params` + `headers` + `body:json`(写接口)
97
+ - `tests { test("name", function() { ... }) }` 内嵌断言(旧版语法)
98
+ - `docs { 业务说明 / 关联需求 spec 列表 }`
99
+
100
+ ### 拿不到真实数据时
101
+
102
+ AI 在以下情况拿不到真实数据:
103
+ - DB 无相关数据(表空 / 无匹配 id)
104
+ - 代码无可推断默认值(参数是用户输入型,如 `phone`、`email`)
105
+
106
+ 处理:
107
+ 1. 在 .bru 留 `{{var}}` 占位
108
+ 2. 在测试规格 §3 标注该参数"需用户手填"
109
+ 3. **不因此中断**,继续生成其他能生成的 .bru
110
+
111
+ 理由:部分参数没值不代表整个 feature 不能跑测试;能跑的部分先跑,漏的让用户补。
112
+
113
+ ### 失败处理
114
+
115
+ AI 调用失败(超时 / 限流):
116
+ - 报"AI 增强失败"
117
+ - 保留已生成的测试规格(S2 产出)
118
+ - **不继续 S4**(环境准备)
119
+
120
+ 理由:S3 没出 .bru,S4 准备环境也没意义;让用户判断是重跑 write-api 还是手动调整。
121
+
122
+ ---
123
+
124
+ ## 跨步骤约束
125
+
126
+ ### 降级处理
127
+
128
+ | 项目状态 | S3 降级行为 |
129
+ |---|---|
130
+ | 未接入 cgraphx 索引 | S3 用 grep + Read 兜底拿 handler 源码,精度可能下降;在测试规格 §4 标注 |
131
+ | 未配置 db-query profile | S3 留 `{{var}}` 占位 + 测试规格 §4 标注"DB 查询不可用";后续 `/run-api-test` 的 R4 也会降级,标"无法核实" |
132
+
133
+ 降级不中断 skill,继续跑能跑的部分。
@@ -0,0 +1,108 @@
1
+ # S2 测试规格文档格式规范
2
+
3
+ ## 六节结构(必须完整)
4
+
5
+ 测试规格文档 `<文件前缀>-api-spec.md` 必须含以下六节,顺序固定:
6
+
7
+ ### §1. 接口清单
8
+
9
+ ```markdown
10
+ ## 1. 接口清单
11
+
12
+ | 方法 | 路径 | handler | 服务 | 通用 | 是否写接口 |
13
+ |---|---|---|---|---|---|
14
+ | GET | /api/v1/users/:id | UserController.getUser | user-service | no | 否 |
15
+ | POST | /api/v1/users | UserController.create | user-service | no | 是 |
16
+ | POST | /api/v1/auth/login | AuthController.login | - | yes | 是 |
17
+ ```
18
+
19
+ - **服务**列:由 AI 在 S2 判断(见 `ai-prompts.md` §S2 微服务识别),无服务划分时填 `-` 或 `(无)`
20
+ - **通用**列:由 AI 在 S2 判断(见 `ai-prompts.md` §S2 通用接口判断),值为 `yes` / `no`
21
+ - 用户可在 S3 前手动校正这两列,skill 以校正后为准
22
+
23
+ ### §2. 测试场景
24
+
25
+ 每个接口列正常 / 边界 / 异常场景:
26
+
27
+ ```markdown
28
+ ### GET /api/v1/users/:id
29
+ - 正常场景:存在 id,返回 200 + 用户详情
30
+ - 边界场景:id 不存在,返回 404
31
+ - 异常场景:id 格式非法,返回 400
32
+ ```
33
+
34
+ ### §3. 测试数据
35
+
36
+ 按场景列参数,标注获取方式(代码提取 / DB 查询 / AI 推断 / 用户手填):
37
+
38
+ ```markdown
39
+ ### GET /api/v1/users/:id
40
+ | 场景 | 参数 | 值 | 获取方式 |
41
+ |---|---|---|---|
42
+ | 正常 | id | 12345 | DB 查询(users 表取已有 id) |
43
+ | 不存在 | id | 999999 | AI 推断 |
44
+ ```
45
+
46
+ - 标"用户手填"的参数:在 .bru 里留 `{{var}}` 占位,跑前需用户填
47
+ - 获取方式决定 S3 生成 .bru 时参数从哪取
48
+
49
+ ### §4. 数据获取方式
50
+
51
+ 汇总本 feature 测试数据来源 + 指明哪些需用户确认 / 补充 + 降级说明:
52
+
53
+ ```markdown
54
+ 本 feature 测试数据来源:
55
+ - 代码提取:从 handler 源码拿默认值、必填项、参数类型
56
+ - DB 查询:通过 db-query skill 查 users 表取真实 id;查 inst_attr 表取真实 attr_id
57
+ - AI 推断:组装符合校验规则的测试值(手机号、邮箱格式等)
58
+ - 用户手填:以下参数需用户在跑前确认或补充:
59
+ - {{token}}:登录 token
60
+ - {{admin_user_id}}:管理员用户 id
61
+
62
+ 降级说明(仅在降级时填,正常情况删):
63
+ - 未接入 cgraphx:S3 用 grep + Read 兜底,参数提取精度可能下降
64
+ - 未配置 db-query:S3 留 {{var}} 占位,S6 DB 核实标"无法核实"
65
+ ```
66
+
67
+ ### §5. 接口映射
68
+
69
+ 场景 → 接口 → .bru 文件路径,路径指向 `docs/bruno/` 下的实际位置:
70
+
71
+ ```markdown
72
+ | 场景 | 接口 | .bru 文件路径 |
73
+ |---|---|---|
74
+ | GET /api/v1/users/:id 正常 | GET /api/v1/users/:id | docs/bruno/user-service/getUser/正常.bru |
75
+ | POST /api/v1/users 缺必填 | POST /api/v1/users | docs/bruno/user-service/createUser/缺name.bru |
76
+ | POST /api/v1/auth/login 正常 | POST /api/v1/auth/login | docs/bruno/common/login/正常.bru |
77
+ ```
78
+
79
+ - 路径规则见 `collection-layout.md`
80
+ - 此映射是下游 `/run-api-test` R1 拿 .bru 清单的来源,必须写全
81
+
82
+ ### §6. 验收口径
83
+
84
+ 明确什么算通过、什么不算:
85
+
86
+ ```markdown
87
+ 通过:
88
+ - 查询接口:HTTP 200 + 断言通(响应体关键字段符合预期)
89
+ - 写接口:HTTP 2xx + 断言通 + DB 核实通(数据真的写了/改了/删了,字段值正确)
90
+ - 通用接口:同查询/写接口规则
91
+
92
+ 不算通过:
93
+ - HTTP 200 但断言失败 → 失败-断言
94
+ - HTTP 200 + 断言通但 DB 数据错 → 失败-DB副作用
95
+ - 4xx / 5xx → 失败-HTTP
96
+ - 超时 / connection refused(服务就绪后)→ 失败-连接
97
+ ```
98
+
99
+ ## 模板
100
+
101
+ 完整填充示例见 `assets/template-api-spec.md`,AI 生成时以它为骨架填充。
102
+
103
+ ## 与下游 skill 的契约
104
+
105
+ - §1 的"服务"和"通用"列 → 驱动 S3 .bru 落盘路径(见 `collection-layout.md`)
106
+ - §3 的获取方式 → 驱动 S3 参数填充策略(见 `bru-format.md` 入参规则)
107
+ - §5 的映射 → 下游 `/run-api-test` R1 拿 .bru 清单的来源,必须与实际 .bru 文件一一对应(否则 `/run-api-test` 会报"对应 .bru 缺失")
108
+ - §4 的降级说明 → 让用户和下游 skill 知道哪些核实会降级
@@ -0,0 +1,144 @@
1
+ # S3 .bru 文件格式规范
2
+
3
+ ## 各段结构(必须含)
4
+
5
+ 每个 .bru 符合 bruno-lang v2 语法,段顺序固定:
6
+
7
+ ```
8
+ meta {
9
+ name: <场景名,如 正常 / 缺prodInstId / 产品不存在>
10
+ type: http
11
+ }
12
+
13
+ # HTTP 方法段:get / post / put / delete / patch
14
+ get {
15
+ url: {{baseUrl}}/api/v1/users/:id
16
+ body: none
17
+ }
18
+
19
+ # 写接口示例:
20
+ # post {
21
+ # url: {{baseUrl}}/api/v1/users
22
+ # body: json
23
+ # }
24
+
25
+ params:query {
26
+ # 查询参数,写真实值
27
+ }
28
+
29
+ params:path {
30
+ # 路径参数,写真实值(如 id: 12345)
31
+ # 唯一例外:前置接口动态传递的值用 {{var}}
32
+ id: 12345
33
+ }
34
+
35
+ headers {
36
+ Content-Type: application/json
37
+ # 鉴权 header 由 AI 按项目既有 .bru + environments/local.bru 的变量名对齐后追加
38
+ # 不同项目鉴权方式不同(accesstoken/staffcode/regionid 或 Authorization/X-API-Key 等)
39
+ # 不在此硬编码示例,避免 AI 套模板
40
+ }
41
+
42
+ # 写接口的请求体(查询接口删此段):
43
+ # 入参写真实值,不变量化
44
+ # body:json {
45
+ # {
46
+ # "name": "测试用户",
47
+ # "email": "test@example.com"
48
+ # }
49
+ # }
50
+
51
+ tests {
52
+ # 用旧版 tests 语法(见下方"断言语法")
53
+ }
54
+
55
+ docs {
56
+ # 见下方"docs 段写法"
57
+ 业务说明: <一句话>
58
+
59
+ 关联需求:
60
+ - <YYYY-MM-DD-feature-id> (<文件前缀>-spec.md)
61
+ }
62
+ ```
63
+
64
+ ## 断言语法(必须用旧版)
65
+
66
+ **必须用** `test("name", function() { ... })` + `res.getStatus()` / `res.getBody()` 旧版语法——这是项目既有 bruno 版本支持的写法,新版语法 `function onResponse(request, response)` 不认。
67
+
68
+ **不要用** `assert { ... }` 段——项目 bruno 版本可能不支持,断言全放 `tests` 段。
69
+
70
+ 断言内容:
71
+
72
+ ```bru
73
+ tests {
74
+ test("HTTP 200", function() {
75
+ expect(res.getStatus()).to.equal(200);
76
+ });
77
+
78
+ test("响应体关键字段", function() {
79
+ const body = JSON.parse(res.getBody());
80
+ expect(body.code).to.equal(0);
81
+ expect(body.data).to.exist;
82
+ });
83
+
84
+ # 写接口额外写 DB 副作用预期注释,供下游 /run-api-test 的 R4 AI 核实参考:
85
+ # DB 预期:users 表新增一行,name=测试用户,email=test@example.com
86
+ # DB 鄄期:user_profile 表同步新增一行,user_id=本次返回的 id
87
+ }
88
+ ```
89
+
90
+ ### 断言内容要求
91
+
92
+ - **HTTP 状态码断言** — 每个场景都要(正常场景通常 200/201,异常场景可能 400/404/409)
93
+ - **响应体关键字段断言** — 从 spec 接口语义或代码返回结构提取,用 `JSON.parse(res.getBody())` 取 body
94
+ - **写接口额外写 DB 副作用预期注释** — 用 `#` 注释,写预期会写/改/删哪些表哪些字段,供 `/run-api-test` R4 AI 核实参考
95
+
96
+ ## 入参写真实值,不变量化
97
+
98
+ 接口入参(如 `prodInstId`)优先写 AI 从 DB 查到或代码推断的**真实值**,直接写死在 `body:json` / `params` 段里。
99
+
100
+ **不变量化的理由**:入参是测试数据,每次跑测试应该用具体值才能稳定复现;变量化只用于"跨环境或跨接口的动态值"。
101
+
102
+ `{{var}}` 占位**只在以下三种情况使用**:
103
+
104
+ | 场景 | 说明 |
105
+ |---|---|
106
+ | 环境级变量 | `baseUrl`、服务端口、鉴权凭据等 → 写在 `environments/local.bru` 里,.bru 用 `{{var}}` 引用 |
107
+ | 前置接口动态传递 | 登录 token、前接口返回 id 等 → 用 `vars:post-response` 段提取,.bru 用 `{{var}}` 引用 |
108
+ | AI 拿不到真实值 | DB 无数据、代码无可推断默认值时 → 留 `{{var}}` 占位 + 测试规格 §3 标注"需用户手填" |
109
+
110
+ 第 3 种情况发生时,在测试规格 §3 标注哪些参数需用户手填,skill 继续跑能跑的部分,不因此中断。
111
+
112
+ ## docs 段写法(固定结构)
113
+
114
+ ```
115
+ docs {
116
+ 业务说明: <一句话,从 Javadoc 或 spec 提取;提取不到占位"(scan 阶段未提取到 Javadoc,请补充业务说明)">
117
+
118
+ 关联需求:
119
+ - <YYYY-MM-DD-feature-id> (<文件前缀>-spec.md)
120
+ }
121
+ ```
122
+
123
+ ### 关联需求列表的行为
124
+
125
+ - AI 生成时,若该接口目录下已有 .bru(docs 段含历史关联需求),把当前 feature-id **追加**到列表(去重),不删除已有 feature
126
+ - 不在 docs 段写断言推理 / 场景预期等详细内容(简短,bruno 不渲染 markdown)
127
+ - **关联需求列表是 `/run-api-test` 反查"接口关联哪些 feature"的依据**——用户触发 `/run-api-test` 只指定接口时,AI 反查此列表让用户选测哪个 feature;列表必须写全,不能漏
128
+
129
+ ## header 名 / 变量名对齐
130
+
131
+ AI 生成 headers 段时,必须先看项目既有 .bru 的 header 名和 `{{var}}` 变量名大小写(如 `accesstoken` vs `accessToken`),避免大小写漂移导致 env 注入失败。
132
+
133
+ 不同项目鉴权方式不同:
134
+
135
+ | 项目示例 | 鉴权 header |
136
+ |---|---|
137
+ | hx 项目 | `accesstoken` / `staffcode` / `regionid`(全小写) |
138
+ | 其他项目 | 可能是 `Authorization: Bearer xxx` / `X-API-Key: xxx` 等 |
139
+
140
+ AI 按目标项目实际探明,不套任何模板示例。
141
+
142
+ ## 模板
143
+
144
+ 完整骨架见 `assets/template-request.bru`。
@@ -0,0 +1,81 @@
1
+ # S3 .bru collection 目录组织规范
2
+
3
+ ## 目录结构
4
+
5
+ ```
6
+ docs/bruno/
7
+ ├── bruno.json # 根级,bruno app 靠此识别整个 docs/bruno/ 为 collection
8
+ ├── environments/ # bruno 原生运行时环境配置(见 environment-setup.md)
9
+ │ ├── local.bru
10
+ │ ├── staging.bru
11
+ │ └── production.bru
12
+ ├── common/ # 通用接口,跨服务跨 feature 复用
13
+ │ └── <接口名>/
14
+ │ └── <场景>.bru
15
+ └── <服务名>/ # 微服务,无服务划分时退化为此层不存在
16
+ └── <接口名>/ # 接口目录,跨 feature 累积场景
17
+ ├── <场景-1>.bru
18
+ └── <场景-2>.bru
19
+ ```
20
+
21
+ ## 路径规则
22
+
23
+ | 接口类型 | 路径 |
24
+ |---|---|
25
+ | 业务接口(有服务划分) | `docs/bruno/<服务>/<接口名>/<场景>.bru` |
26
+ | 业务接口(无服务划分) | `docs/bruno/<接口名>/<场景>.bru` |
27
+ | 通用接口 | `docs/bruno/common/<接口名>/<场景>.bru` |
28
+
29
+ ### 取名规则
30
+
31
+ - **`<服务>`** — 由 AI 在 S2 识别(见 `ai-prompts.md`),参考 `docs/bruno/` 既有目录名保持一致
32
+ - **`<接口名>`** — 取接口的方法名或路径最后一段,参考项目既有 .bru 的命名习惯
33
+ - **`<场景>`** — 取测试规格 §2 的场景名(如 `正常` / `缺prodInstId` / `产品不存在`)
34
+
35
+ ## 按接口组织,不绑 feature-id
36
+
37
+ **核心原则**:接口跨 feature 复用,按 `<接口名>` 组织目录,**不绑 feature-id**。
38
+
39
+ 不同 feature 测同一接口时,往同一接口目录追加场景 .bru,而不是按 feature-id 分目录。理由:同一接口的测试应该集中管理,方便跨 feature 回归。
40
+
41
+ ## 跨 feature 同接口同场景覆盖
42
+
43
+ 不同 feature 测同一接口的同一场景时,**后跑的覆盖先跑的 .bru**。
44
+
45
+ 理由:测哪个需求就从当前需求 spec + DB 重新取数据,不保留历史入参(历史入参会过时,留着误导)。
46
+
47
+ **例外**:docs 段的"关联需求"列表**不覆盖**,而是去重追加——记录该接口关联过哪些 feature,供 `/run-api-test` 反查。
48
+
49
+ ## 不生成 per-folder collection.bru
50
+
51
+ bruno 的 folder 不需要 `collection.bru`,只在 `docs/bruno/` 根级有一个 `bruno.json`(见下方)。
52
+
53
+ ## 根级 bruno.json
54
+
55
+ 若 `docs/bruno/bruno.json` 不存在,生成:
56
+
57
+ ```json
58
+ {
59
+ "version": 1,
60
+ "name": "<project>-api-test",
61
+ "type": "collection"
62
+ }
63
+ ```
64
+
65
+ `<project>` 取项目根目录名(如 `hx`、`zq` 等)。
66
+
67
+ 已存在则**不覆盖**,沿用用户配置。
68
+
69
+ ## 首次接入
70
+
71
+ 项目首次接入时,`docs/bruno/` 不存在,skill 自动创建:
72
+
73
+ - `docs/bruno/` 目录
74
+ - `bruno.json`
75
+ - `environments/` 目录(见 `environment-setup.md`)
76
+
77
+ 不报错,不需要用户手动准备。
78
+
79
+ ## 与测试规格文档的契约
80
+
81
+ 测试规格 §5 接口映射里的路径必须与实际落盘路径**一一对应**,否则下游 `/run-api-test` R1 拿到 .bru 清单后会报"对应 .bru 缺失"。
@@ -0,0 +1,105 @@
1
+ # S4 bruno 环境配置规范
2
+
3
+ ## 文件位置与格式
4
+
5
+ ```
6
+ docs/bruno/environments/
7
+ ├── local.bru # 本地环境(默认)
8
+ ├── staging.bru # 测试环境
9
+ └── production.bru # 生产环境
10
+ ```
11
+
12
+ 每个 .bru 是 bruno 原生运行时格式,`vars { ... }` 段:
13
+
14
+ ```
15
+ vars {
16
+ <服务名或baseUrl>: http://127.0.0.1:<端口>
17
+ <非敏感业务变量>: <值>
18
+ <鉴权变量1>:
19
+ <鉴权变量2>:
20
+ }
21
+ ```
22
+
23
+ 环境名固定三档,英文:`local` / `staging` / `production`(避免命令行传中文编码问题)。
24
+
25
+ ## 首次接入生成逻辑
26
+
27
+ `docs/bruno/environments/local.bru` 不存在时,skill 生成三个 .bru 文件骨架,然后:
28
+
29
+ ### non-secret 变量(AI 填)
30
+
31
+ AI 扫项目配置(pom.xml / package.json / application.yml / go.mod 等)探明端口,填入 `local.bru`:
32
+ - 服务的地址变量(如 `so-assist: http://127.0.0.1:8087`)
33
+ - region、租户等非敏感业务变量
34
+
35
+ `staging.bru` / `production.bru` 的 non-secret **留空**,提示用户填(避免 AI 瞎猜外部环境地址)。
36
+
37
+ ### secret 变量(AI 决定字段名,值留空)
38
+
39
+ AI 看项目既有 .bru 的**鉴权 header 名**决定有哪些 secret 字段:
40
+
41
+ - 若既有 .bru 用 `accesstoken` / `staffcode` / `regionid` → secret 字段就是这些名
42
+ - 若既有 .bru 用 `Authorization` / `X-API-Key` → secret 字段就是 `Authorization` / `xApiKey`
43
+ - 不固定 hx 的字段名,其他项目不同
44
+
45
+ **值留空**,字段加 `secret: true`(bruno-environment 格式支持;bruno 原生 .bru 格式无 secret 标记,值留空即可,bruno app 里手动标 secret)。
46
+
47
+ ### 生成后暂停
48
+
49
+ skill 暂停提示用户:
50
+
51
+ ```
52
+ 环境配置已生成骨架:
53
+ - docs/bruno/environments/local.bru(non-secret 已填,secret 留空)
54
+ - docs/bruno/environments/staging.bru(全空)
55
+ - docs/bruno/environments/production.bru(全空)
56
+
57
+ 请填 local.bru 的 secret 变量(staffcode/accesstoken 等),填完回车继续。
58
+ ```
59
+
60
+ 不直接结束,等用户填完回车。
61
+
62
+ ## 已存在不覆盖
63
+
64
+ `docs/bruno/environments/local.bru` 已存在 → 沿用,**不重写**。
65
+
66
+ 理由:用户可能已经手动调过端口或 secret,重写会覆盖用户配置。
67
+
68
+ ## 环境切换
69
+
70
+ - 默认 `local`
71
+ - 用户调用 `/run-api-test --env staging` 切换,透传 `bru run --env staging`
72
+ - write-api 阶段不跑 bru run,所以 write-api 不关心环境切换;环境切换是 `/run-api-test` 的事
73
+
74
+ ## 不自动生成 secret 的理由
75
+
76
+ **为什么 secret 不自动填值**:AI 不应该接触真实 token / 密码 / API key——
77
+ 1. 避免泄露,skill 资产或日志可能记录
78
+ 2. AI 无法知道真实值(这些值通常是用户从浏览器、运维系统手动取的)
79
+ 3. 让用户明确填一次,后续 `environments/local.bru` 沿用,不需要每次跑都填
80
+
81
+ ## 模板示例(参考,不照搬)
82
+
83
+ hx 项目 local.bru 示例(变量名 + 值都是 hx 特定,AI 生成时按目标项目实际探明,**不套此模板**):
84
+
85
+ ```
86
+ vars {
87
+ so-assist: http://127.0.0.1:8087
88
+ regionid: 8323300
89
+ staffcode:
90
+ accesstoken:
91
+ }
92
+ ```
93
+
94
+ 其他项目可能长这样(AI 按 zq 项目探明):
95
+
96
+ ```
97
+ vars {
98
+ baseUrl: http://127.0.0.1:8080
99
+ zqassis: http://127.0.0.1:8080
100
+ Authorization:
101
+ xApiKey:
102
+ }
103
+ ```
104
+
105
+ 变量名和端口都从项目实际探明,不预设。