@epoint-testtech/ep-stage-skill 0.0.9 → 0.5.0-alpha.2

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 (158) hide show
  1. package/SKILL.md +27 -27
  2. package/codex-skill/ep-stage/glue-create-project/SKILL.md +223 -223
  3. package/codex-skill/ep-stage/glue-generate-testcase/SKILL.md +275 -275
  4. package/codex-skill/ep-stage/glue-generate-testcase/examples/observable-testcase.json +40 -40
  5. package/codex-skill/ep-stage/glue-generate-testcase/references/testcase-schema.md +95 -95
  6. package/codex-skill/ep-stage/glue-run-test/SKILL.md +273 -296
  7. package/codex-skill/ep-stage/glue-run-test/references/ai-runtime-loop.md +30 -30
  8. package/codex-skill/ep-stage/glue-run-test/references/crud-pipeline.md +132 -132
  9. package/codex-skill/ep-stage/glue-run-test/references/gap-review-protocol.md +44 -44
  10. package/codex-skill/ep-stage/glue-run-test/references/harness-principles.md +46 -46
  11. package/codex-skill/ep-stage/glue-run-test/references/playwright-cli-odav.md +127 -166
  12. package/codex-skill/ep-stage/glue-run-test/scripts/generate-crud-spec.mjs +149 -149
  13. package/codex-skill/ep-stage/recording-to-glue/SKILL.md +28 -28
  14. package/codex-skill/ep-stage/scripts/validate-skill.mjs +95 -98
  15. package/dist/src/cli/generate-testcase.d.ts +0 -1
  16. package/dist/src/cli/generate-testcase.d.ts.map +1 -1
  17. package/dist/src/cli/generate-testcase.js +1 -6
  18. package/dist/src/cli/index.d.ts.map +1 -1
  19. package/dist/src/cli/index.js +14 -38
  20. package/dist/src/cli/run.d.ts +0 -2
  21. package/dist/src/cli/run.d.ts.map +1 -1
  22. package/dist/src/cli/run.js +21 -70
  23. package/dist/src/cli/spec.d.ts.map +1 -1
  24. package/dist/src/cli/spec.js +0 -9
  25. package/dist/src/contracts/glue-contract-v1.d.ts +0 -35
  26. package/dist/src/contracts/glue-contract-v1.d.ts.map +1 -1
  27. package/dist/src/extractors/code-list-json5.d.ts +1 -34
  28. package/dist/src/extractors/code-list-json5.d.ts.map +1 -1
  29. package/dist/src/extractors/code-list-json5.js +0 -1
  30. package/dist/src/extractors/html-page.d.ts +0 -9
  31. package/dist/src/extractors/html-page.d.ts.map +1 -1
  32. package/dist/src/extractors/html-page.js +2 -26
  33. package/dist/src/generators/agent-inferred-workflow-script.js +66 -66
  34. package/dist/src/generators/stage-skeleton-script.d.ts +0 -50
  35. package/dist/src/generators/stage-skeleton-script.d.ts.map +1 -1
  36. package/dist/src/generators/stage-skeleton-script.js +116 -449
  37. package/dist/src/runtime/ai-runtime-trace.d.ts.map +1 -1
  38. package/dist/src/runtime/ai-runtime-trace.js +0 -8
  39. package/dist/src/testcase/contract-testcase-assembler.d.ts +0 -28
  40. package/dist/src/testcase/contract-testcase-assembler.d.ts.map +1 -1
  41. package/dist/src/testcase/contract-testcase-assembler.js +75 -329
  42. package/dist/src/validation/contract.d.ts.map +1 -1
  43. package/dist/src/validation/contract.js +0 -29
  44. package/dist/test/cli/generate-testcase-json5.test.d.ts +2 -0
  45. package/dist/test/cli/generate-testcase-json5.test.d.ts.map +1 -0
  46. package/dist/test/cli/generate-testcase-json5.test.js +154 -0
  47. package/dist/test/cli/index.test.d.ts +2 -0
  48. package/dist/test/cli/index.test.d.ts.map +1 -0
  49. package/dist/test/cli/index.test.js +114 -0
  50. package/dist/test/cli/run.test.d.ts +2 -0
  51. package/dist/test/cli/run.test.d.ts.map +1 -0
  52. package/dist/test/cli/run.test.js +429 -0
  53. package/dist/test/cli/spec.test.d.ts +2 -0
  54. package/dist/test/cli/spec.test.d.ts.map +1 -0
  55. package/dist/test/cli/spec.test.js +112 -0
  56. package/dist/test/code-list-json5.test.d.ts +2 -0
  57. package/dist/test/code-list-json5.test.d.ts.map +1 -0
  58. package/dist/test/code-list-json5.test.js +84 -0
  59. package/dist/test/code-list.test.d.ts +2 -0
  60. package/dist/test/code-list.test.d.ts.map +1 -0
  61. package/dist/test/code-list.test.js +39 -0
  62. package/dist/test/gap-inference.test.d.ts +2 -0
  63. package/dist/test/gap-inference.test.d.ts.map +1 -0
  64. package/dist/test/gap-inference.test.js +597 -0
  65. package/dist/test/generalization.test.d.ts +2 -0
  66. package/dist/test/generalization.test.d.ts.map +1 -0
  67. package/dist/test/generalization.test.js +73 -0
  68. package/dist/test/material-inventory.test.d.ts +2 -0
  69. package/dist/test/material-inventory.test.d.ts.map +1 -0
  70. package/dist/test/material-inventory.test.js +155 -0
  71. package/dist/test/observable-chain.test.d.ts +2 -0
  72. package/dist/test/observable-chain.test.d.ts.map +1 -0
  73. package/dist/test/observable-chain.test.js +123 -0
  74. package/dist/test/page-structure.test.d.ts +2 -0
  75. package/dist/test/page-structure.test.d.ts.map +1 -0
  76. package/dist/test/page-structure.test.js +45 -0
  77. package/dist/test/runtime/ai-runtime-trace.test.d.ts +2 -0
  78. package/dist/test/runtime/ai-runtime-trace.test.d.ts.map +1 -0
  79. package/dist/test/runtime/ai-runtime-trace.test.js +78 -0
  80. package/dist/test/scenario-inference.test.d.ts +2 -0
  81. package/dist/test/scenario-inference.test.d.ts.map +1 -0
  82. package/dist/test/scenario-inference.test.js +73 -0
  83. package/dist/test/stage-context.test.d.ts +2 -0
  84. package/dist/test/stage-context.test.d.ts.map +1 -0
  85. package/dist/test/stage-context.test.js +395 -0
  86. package/dist/test/testcase/testcase-markdown.test.d.ts +2 -0
  87. package/dist/test/testcase/testcase-markdown.test.d.ts.map +1 -0
  88. package/dist/test/testcase/testcase-markdown.test.js +48 -0
  89. package/dist/test/testcase-generator.test.d.ts +2 -0
  90. package/dist/test/testcase-generator.test.d.ts.map +1 -0
  91. package/dist/test/testcase-generator.test.js +276 -0
  92. package/dist/test/testcase-skeleton.test.d.ts +2 -0
  93. package/dist/test/testcase-skeleton.test.d.ts.map +1 -0
  94. package/dist/test/testcase-skeleton.test.js +185 -0
  95. package/dist/test/testcase-spec-assembly.test.d.ts +2 -0
  96. package/dist/test/testcase-spec-assembly.test.d.ts.map +1 -0
  97. package/dist/test/testcase-spec-assembly.test.js +105 -0
  98. package/dist/test/util/credentials.test.d.ts +2 -0
  99. package/dist/test/util/credentials.test.d.ts.map +1 -0
  100. package/dist/test/util/credentials.test.js +64 -0
  101. package/dist/test/util/i18n-testcase.test.d.ts +2 -0
  102. package/dist/test/util/i18n-testcase.test.d.ts.map +1 -0
  103. package/dist/test/util/i18n-testcase.test.js +119 -0
  104. package/dist/test/util/softlink.test.d.ts +2 -0
  105. package/dist/test/util/softlink.test.d.ts.map +1 -0
  106. package/dist/test/util/softlink.test.js +82 -0
  107. package/dist/test/validation/contract.test.d.ts +2 -0
  108. package/dist/test/validation/contract.test.d.ts.map +1 -0
  109. package/dist/test/validation/contract.test.js +116 -0
  110. package/dist/test/validation/credentials.test.d.ts +2 -0
  111. package/dist/test/validation/credentials.test.d.ts.map +1 -0
  112. package/dist/test/validation/credentials.test.js +74 -0
  113. package/dist/test/validation/projects-index.test.d.ts +2 -0
  114. package/dist/test/validation/projects-index.test.d.ts.map +1 -0
  115. package/dist/test/validation/projects-index.test.js +48 -0
  116. package/dist/test/validation/testcase-v1-draft.test.d.ts +2 -0
  117. package/dist/test/validation/testcase-v1-draft.test.d.ts.map +1 -0
  118. package/dist/test/validation/testcase-v1-draft.test.js +173 -0
  119. package/dist/vitest.config.d.ts +3 -0
  120. package/dist/vitest.config.d.ts.map +1 -0
  121. package/dist/vitest.config.js +7 -0
  122. package/docs/README.md +124 -124
  123. package/examples/schemeresource-observable-docs/schemeresource.context.md +20 -20
  124. package/examples/schemeresource.module-hints.json +38 -38
  125. package/examples/schemeresource.observable.code_list.md +37 -37
  126. package/examples/zwplace-observable-docs/zwplace.context.md +16 -16
  127. package/examples/zwplace-placecategory-validation.json +29 -29
  128. package/examples/zwplace.module-hints.json +69 -69
  129. package/examples/zwplace.observable.code_list.md +37 -37
  130. package/package.json +19 -13
  131. package/codex-skill/ep-stage/glue-generate-testcase/references/testcase-tpl.md +0 -72
  132. package/codex-skill/ep-stage/glue-run-test/scripts/extract-page-elements-eval.mjs +0 -233
  133. package/codex-skill/ep-stage/page-element-scan/SKILL.md +0 -91
  134. package/codex-skill/ep-stage/page-element-scan/evals/evals.json +0 -37
  135. package/codex-skill/ep-stage/page-element-scan/evals/fixtures/sample-list-page.html +0 -85
  136. package/codex-skill/ep-stage/page-element-scan/references/pagination-controls.md +0 -153
  137. package/codex-skill/ep-stage/page-element-scan/scripts/extract-page-elements-eval.mjs +0 -233
  138. package/codex-skill/ep-stage/page-element-scan/scripts/extract-page-elements.mjs +0 -298
  139. package/codex-skill/ep-stage/page-element-scan/scripts/scan-page.mjs +0 -749
  140. package/dist/src/cli/probe.d.ts +0 -46
  141. package/dist/src/cli/probe.d.ts.map +0 -1
  142. package/dist/src/cli/probe.js +0 -447
  143. package/dist/src/cli/run-report.d.ts +0 -46
  144. package/dist/src/cli/run-report.d.ts.map +0 -1
  145. package/dist/src/cli/run-report.js +0 -316
  146. package/dist/src/extractors/prd-extractor.d.ts +0 -70
  147. package/dist/src/extractors/prd-extractor.d.ts.map +0 -1
  148. package/dist/src/extractors/prd-extractor.js +0 -248
  149. package/dist/src/testcase/button-interaction-inference.d.ts +0 -37
  150. package/dist/src/testcase/button-interaction-inference.d.ts.map +0 -1
  151. package/dist/src/testcase/button-interaction-inference.js +0 -385
  152. package/dist/src/testcase/prd-button-mapper.d.ts +0 -72
  153. package/dist/src/testcase/prd-button-mapper.d.ts.map +0 -1
  154. package/dist/src/testcase/prd-button-mapper.js +0 -148
  155. package/dist/src/testcase/testcase-v2.d.ts +0 -50
  156. package/dist/src/testcase/testcase-v2.d.ts.map +0 -1
  157. package/dist/src/testcase/testcase-v2.js +0 -1
  158. package/docs/mvp-usage-guide.md +0 -298
@@ -1,275 +1,275 @@
1
- ---
2
- name: glue-generate-testcase
3
- description: 使用时机:当用户对某需求要「生成用例 / 准备测试场景 / 钻探上游需求生成胶水冒烟用例」或显式触发 `/glue-generate-testcase <code_list.json5路径>` 时使用。本 skill 包装 `@epoint-testtech/ep-stage-skill` CLI 的 `testcase` 子命令,并负责自然语言映射、缺数据引导、Step 5 凭据交互确认。
4
- version: 2026-08-12+925f4c4
5
- argument-hint: "<code_list.json5绝对/相对路径>"
6
- ---
7
-
8
- # ep-stage: glue-generate-testcase
9
-
10
- 本 skill 引导 Agent **包装** `@epoint-testtech/ep-stage-skill` CLI 的 `testcase` 子命令,不重新实现钻探与用例生成。CLI 内部完成物料解析 + contract 提取(内嵌)+ coverage 分析 + testcase 装配 + credentials.template 生成。skill 负责:`code_list.json5` 路径解析、反查项目脚手架、缺数据引导、Step 5 平台对话确认凭据、审阅引导。用户视角全中文,不暴露 CLI 名称。
11
-
12
- > **契约可观测性 gate**:每个非平凡字段必须能追溯到上游证据、可重复推导规则、运行配置来源或人工确认问题;无法给出来源的字段必须进入 `unresolvedSlots`,禁止写入 `contract.json5`。"无来源不入契约"。
13
-
14
- > 钻探前置:testcase.json5 顶层(schemaVersion:'ep-stage-testcase/v1-draft' + testcaseId + contractRef + scenario + moduleId + moduleName + runtimeContext? + testAccess? + cases + uncoveredCandidates)由 CLI 一次写入。scenario 由 CLI 按 `code_list.json5` 推导(assembler),014 默认 `crud_export`;scenario 作为**产物**(非输入)写入顶层。`menuPath` 不是新链路必填字段。`runtimeContext` 用于落定工程与 spec 路径;`testAccess` 只保存 `credentialRef/requiredRoles`,明文账号密码与运行访问数据统一写入 `credentials.json5`。`directUrl` 是待测页面直达地址,不属于上游出码事实;缺失时必须在本 skill 交互补齐,并通过 CLI 参数写入 `contract.json5.base.navigation.directUrl`。**module-hints 已废弃**(交接文档 §4.1),不作为输入。
15
-
16
- ## 1. 自然语言映射
17
-
18
- ```text
19
- /glue-generate-testcase /abs/path/.../014-测试需求10-20260622/_docs/code_list.json5 # 绝对路径
20
- /glue-generate-testcase ../knowledge-project/.../014-测试需求10-20260622/_docs/code_list.json5 # 相对路径
21
- /glue-generate-testcase # 无参数 → 问 code_list.json5 路径
22
- /glue-generate-testcase /abs/path/.../014-测试需求10-20260622/_docs/code_list.json5 --debug # 调试模式 → 跑本地 ep-stage-skill dist
23
- ```
24
-
25
- > **`--debug` flag**:正常调用走远程 `npx @epoint-testtech/ep-stage-skill@latest`。开发期想测试未发布的本地代码时传 `--debug`,skill 在 Step 4 改用 `node <repo>/packages/ep-stage-skill/dist/src/cli/index.js`。前提:cwd 在 ep-stage monorepo 内(向上能找到 `pnpm-workspace.yaml`);找不到时直接 exit 1 报错,不静默 fallback 到 npx。
26
-
27
- `--scenario` 不作为正常路径输入(scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`);`--hints` / module-hints 已废弃,不作为输入。
28
-
29
- skill 把 `code_list.json5` 入参 `path.resolve` 绝对化,用其父目录的父目录 basename 取「需求名」作为 `<projectDir>/src/tests/<需求名>` 子目录(`_docs/code_list.json5` 上一级即需求目录)。**projectDir 不接受参数**,全部从 `~/.ep-stage/projects.index.json5` 反查最新 `mode: 'glue'` 条目(多条 AskUserQuestion 让用户挑);索引缺失走引导场景 A。
30
-
31
- ## 2. Agent 执行剧本(8 步任务清单协议)
32
-
33
- **任务清单协议(REQ-UX-01)**:load 后**最先**单行展示技能版本(取本 SKILL.md frontmatter 的 `version` 字段),格式 `技能版本:glue-generate-testcase <version>`;随后**立即**打印初始任务清单(Step 0);每完成一步输出单行 `第 N 步 — <中文名> 已完成,进入第 N+1 步 — <下一中文名>...`;Step 8 输出全勾选终态清单 + 摘要。
34
-
35
- ### Step 0 — 打印任务清单
36
-
37
- ```markdown
38
- **生成胶水测试用例任务清单**
39
-
40
- - [ ] 第 1 步 — 解析 code_list.json5 路径
41
- - [ ] 第 2 步 — 反查项目脚手架
42
- - [ ] 第 3 步 — 校验 code_list.json5 输入
43
- - [ ] 第 4 步 — 补齐待测页面 directUrl 并调用钻探与用例生成 CLI
44
- - [ ] 第 5 步 — 与研发人员交互确认推断结果
45
- - [ ] 第 6 步 — 校验产物完整性 + 审阅 testcase.md 单表
46
- - [ ] 第 7 步 — 写入需求条目到项目索引
47
- - [ ] 第 8 步 — 输出审阅引导摘要
48
- ```
49
-
50
- ### Step 1 — 解析 code_list 路径
51
-
52
- 从用户消息 / args 抽取 `code_list.json5` 路径,绝对化后得到 `codeListPath`,再用其父目录的父目录 basename 作为需求名(`_docs/code_list.json5` 上一级即需求目录)。中文复述识别结果:"已识别:code_list.json5 = `<abs>`,需求名 = `<basename>`"。入参缺失 → free text 询问"请给我 code_list.json5 的绝对或相对路径(位于需求目录 `_docs/` 下)"。
53
-
54
- ### Step 2 — 反查项目脚手架(缺 → 引导 A)
55
-
56
- 读 `~/.ep-stage/projects.index.json5`:文件不存在 / 无 glue 条目 → **引导场景 A**:中文提示"未发现胶水测试脚手架。请先跑 `/glue-create-project <项目名>` 创建脚手架后再回来",退出不调 CLI。多条匹配 → AskUserQuestion 挑 projectDir。单条 → 直接拼 `--tests-dir` 根。
57
-
58
- ### Step 3 — 校验 code_list.json5 输入(缺 → 引导 D)
59
-
60
- 校验 `codeListPath` 是否存在,且 `code_list.json5` 内至少给出:
61
- - `knowledgeRoot: /abs/path`,或
62
- - `> 整理目录:\`/abs/path\``
63
-
64
- 其余物料路径默认视为相对该根目录的路径;若某项缺失或不存在,再进入交互补齐。`codeListPath` 本身缺失 → **引导场景 D**,AskUserQuestion 三选一:
65
-
66
- 1. **提供 code_list.json5 路径**:让用户给绝对路径(位于需求目录 `_docs/` 下),skill 改用该路径继续。
67
- 2. **读 PRD 草稿生成 code_list.json5**:在需求目录找 PRD / spec.yaml,AI 推断 `knowledgeRoot` / `menu` / 文件清单写一份 `code_list.json5` 草稿到 `_docs/` 下,提示"已生成草稿,请人审后再跑",退出。
68
- 3. **取消**:直接退出,不调 CLI。
69
-
70
- ### Step 4 — 补齐待测页面 directUrl 并调用钻探与用例生成 CLI
71
-
72
- 固定流程(不 which、不扫 monorepo、不 cd、**不喂 stdin**)。调用 CLI 前先确定待测页面 `directUrl`:
73
-
74
- - 若 `code_list.json5` 已有待测页面节点的 `pages[role=list].directUrl`,直接使用。
75
- - 若缺失,必须用平台对话询问用户:"请提供待测页面直达链接(directUrl)。说明:直达链接通常来自浏览器地址栏中 view-source: 后面的页面地址;例如 view-source:http://192.168.203.46:8100/epoint-web/perpage/zwplace/gxhzwplacelist.html,实际填写 http://192.168.203.46:8100/epoint-web/perpage/zwplace/gxhzwplacelist.html。"
76
- - 仍缺失则停止,不调 CLI。禁止让下游 `glue-run-test` 自行猜入口。
77
-
78
- **正常模式**(用户 args 无 `--debug`):
79
-
80
- ```bash
81
- npx -y @epoint-testtech/ep-stage-skill@latest testcase \
82
- --code-list <codeListPath> \
83
- --tests-dir <projectDir>/src/tests/<需求名> \
84
- --requirement-dir <codeListPath 的父目录> \
85
- --project-dir <projectDir> \
86
- --direct-url <待测列表页 directUrl>
87
- ```
88
-
89
- (scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`,正常路径不传 `--scenario`)
90
-
91
- **调试模式**(用户 args 含 `--debug`,要求 cwd 在 ep-stage monorepo 内;详见 §1 `--debug` flag 说明):
92
-
93
- ```bash
94
- D="$PWD"; REPO=""
95
- while [ "$D" != "/" ]; do
96
- if [ -f "$D/pnpm-workspace.yaml" ] && [ -f "$D/packages/ep-stage-skill/dist/src/cli/index.js" ]; then
97
- REPO="$D"; break
98
- fi
99
- D="$(dirname "$D")"
100
- done
101
- [ -z "$REPO" ] && { echo "错误:--debug 但找不到本地 monorepo(需 cwd 在 ep-stage 仓库内向上能找到 pnpm-workspace.yaml + packages/ep-stage-skill/dist/src/cli/index.js)"; exit 1; }
102
- echo "调试模式:本地 $REPO/packages/ep-stage-skill/dist/src/cli/index.js"
103
- node "$REPO/packages/ep-stage-skill/dist/src/cli/index.js" testcase \
104
- --code-list <codeListPath> \
105
- --tests-dir <projectDir>/src/tests/<需求名> \
106
- --requirement-dir <codeListPath 的父目录> \
107
- --project-dir <projectDir> \
108
- --direct-url <待测列表页 directUrl>
109
- ```
110
-
111
- (scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`,正常路径不传 `--scenario`)
112
-
113
- CLI 内部:按 `code_list.json5` 解析物料 → assembler 推导 scenario(014 默认 `crud_export`)→ 装配 contract + testcase(scenario 作为产物写入 `testcase.json5` 顶层,`directUrl` 写入 `contract.json5.base.navigation.directUrl`,`testcase.json5.testAccess` 只写 `credentialRef/requiredRoles`)→ schema 门禁 → 写 testcase.json5 / testcase.md(统一单表审阅视图)/ credentials.template.json5 / `.ep-stage/contract.json5` / `.ep-stage/inference-trace.json`。testcase.md 只渲染一张用例表,列为:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言。glue 与 ai 通过“生成策略”列区分,不拆成两个表。CLI 非 0 退出 → 复述 stderr,不发完成提示,不进 Step 5。
114
-
115
- ### Step 5 — 与研发人员交互确认推断结果(REQ-UX-02)
116
-
117
- Step 4 成功后,skill 读 CLI 产出的 `credentials.template.json5`(行数 = `code_list.roles.length`,每条对应一个角色)+ `uncoveredCandidates[].requiredRole`,再读 `~/.ep-stage/projects.index.json5` 的 `systems[]` 算 `cachedSystemsHit`(url 命中的列表)。用**平台对话能力**(Claude Code 用 `AskUserQuestion` / Codex 用对应交互机制)跟用户对话:
118
-
119
- > 推断出 **N 个角色**(如 建设单位 / 施工单位 / 监理单位)。请选择:
120
- > 1. **现在交互输入**(推荐:≤3 角色场景)— 我逐个角色问直达链接(directUrl)/ 登录地址(loginUrl)/ 系统名称(systemName)/ 角色(role)/ 账号(username)/ 密码(password),汇总摘要请你确认后写 `credentials.json5`
121
- > 2. **仅生成 template,自己后续填** — 退出后请拷贝 `credentials.template.json5` → `credentials.json5` 并填值
122
- > 3. **跳过,使用全局 systems[] 缓存复用** — 自动从 `cachedSystemsHit` 命中缓存生成 `credentials.json5`(缺失角色 fallback 引导 C,留给 glue-run-test)
123
-
124
- 三分支处理:
125
-
126
- - **选 1**:skill 顺序问每条角色的直达链接(directUrl)/ 登录地址(loginUrl)/ 系统名称(systemName)/ 角色(role)/ 账号(username)/ 密码(password)(free text)。直达链接问题必须说明其来源是 `view-source:` 后面的页面地址。收集后先展示摘要给用户确认;确认后写 `<需求名>/credentials.json5`(gitignore,非 template),`<需求名>/testcase.json5.testAccess` 只保留 `credentialRef: 'credentials.json5'` 和 `requiredRoles`,**回写**全局 `~/.ep-stage/projects.index.json5` 的 `systems[].credentialsCache`(按 loginUrl 归并,跨需求复用)。
127
- - **选 2**:保留 template;提示"请编辑 `credentials.json5` 后再跑 `/glue-run-test`",进入 Step 6。
128
- - **选 3**:从 `systems[].credentialsCache` 拼出 credentials.json5,缺失角色用 template 占位符保留;`<需求名>/testcase.json5.testAccess` 只保留 `credentialRef: 'credentials.json5'` 和 `requiredRoles`,不写明文账号密码。
129
-
130
- ### Step 6 — 校验产物完整性 + 审阅 testcase.md 单表
131
-
132
- **Step 6.1 — 校验产物完整性**
133
-
134
- 按 §3 验证清单 `ls` / `Read` 校验 CLI 产物存在(除 `testcase.md` 外其他全部,缺任意一项视为整体失败,按 §4 报告):
135
-
136
- - `testcase.json5`、`credentials.template.json5`(或 `credentials.json5`)、`.ep-stage/contract.json5`、`.ep-stage/inference-trace.json`
137
-
138
- Step 6 只需要确认 CLI 已基于 `testcase.json5` 事实源写出 `testcase.md`。该文件固定是一张审阅表,列为:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言。glue 与 ai 统一在同一张表中,通过“生成策略”列区分。每次重跑都会整体覆盖 `testcase.md`;人审意见只写进 `testcase.json5`(JSON5 `// 注释`),不写 `testcase.md`。
139
-
140
- ### Step 7 — 写入需求条目到项目索引
141
-
142
- CLI testcase 子命令在传入 `--project-dir` 时,自动往 `~/.ep-stage/projects.index.json5` 对应 `projects[].requirements[]` 追加本需求条目(含 `name / requirementDir / testsDir / lastRunStatus: "never"`,同名需求去重更新);未传 `--project-dir` 则跳过(不维护 index)。skill Step 4 命令总带 `--project-dir`,故正常流程 CLI 必追加。skill 校验:条目存在;`name` 与 Step 1 一致;`testsDir` 指向 `<projectDir>/src/tests/<需求名>`。
143
-
144
- ### Step 8 — 输出审阅引导摘要
145
-
146
- 打印全勾选终态清单 + §5 完成提示(含审阅引导链:审 testcase.md → 编辑 testcase.json5 → 填 credentials.json5 → 跑 `/glue-run-test`)。
147
-
148
- ## 3. 验证清单
149
-
150
- | 路径 | 说明 |
151
- |--------------------------------------------------------------|--------------------------------------------------------|
152
- | `<projectDir>/src/tests/<需求名>/testcase.json5` | testcase schema v1-draft(schemaVersion / scenario / moduleId / moduleName / menuPath / runtimeContext? / testAccess? / contractRef / cases / uncoveredCandidates),**事实源** |
153
- | `<projectDir>/src/tests/<需求名>/testcase.md` | 基于 `testcase.json5` 渲染的单表审阅视图(列:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言;重跑覆盖) |
154
- | `<projectDir>/src/tests/<需求名>/credentials.template.json5` | 行数 = `code_list.roles.length`(每条对应一个角色) |
155
- | `<projectDir>/src/tests/<需求名>/.ep-stage/contract.json5` | 内部产物,机器专用,禁手编 |
156
- | `<projectDir>/src/tests/<需求名>/.ep-stage/inference-trace.json` | 推理追踪总账,只供排查和审阅,不作为 spec 主输入 |
157
- | `~/.ep-stage/projects.index.json5` | 已追加 `projects[].requirements[]` |
158
-
159
- > 常态不生成 `source-spec.json` 或 `module-hints.inferred.json5`;二者只作为显式调试导出,非正常产物。
160
-
161
- ## 4. 错误处理
162
-
163
- | 触发时机 | Agent 中文呈现 + 建议 |
164
- |-----------------------------------------|----------------------------------------------------------------------|
165
- | 引导 A(缺脚手架) | 中文提示+退出,引导先跑 `/glue-create-project` |
166
- | 引导 D(缺 code_list.json5) | AskUserQuestion 三选一:提供路径 / 读 PRD 草稿 / 取消 |
167
- | CLI exit ≠ 0 | 复述 stderr 中文转述,不发完成提示,不进 Step 5 |
168
- | testcase.json5 缺 `schemaVersion` | 报"产物 schema 校验失败,请重跑 `/glue-generate-testcase <code_list.json5路径>`" |
169
- | Step 5 选 1 用户中途取消 | 保留 template,提示"凭据未写入,请稍后拷贝 template 自填" |
170
- | testcase.md 单表缺失或结构异常 | 复述缺失项或列结构异常,提示检查 testcase.json5 与 CLI 输出后重跑 |
171
-
172
- ## 5. 完成提示
173
-
174
- Step 8 全部通过后,按以下中文格式呈现(不要用 success/done/generated):
175
-
176
- > 用例已生成。
177
- >
178
- > 测试项目:`<projectDir>`
179
- > 用例文件:`<projectDir>/src/tests/<需求名>/testcase.json5`
180
- > 用例摘要:共 N 条,胶水组装 X 条,AI 推理 Y 条
181
- > 重点审核:AI 推理用例、blocked 候选、登录角色信息
182
- >
183
- > 需要调整的话,直接告诉我改哪条用例,我来更新 testcase.json5。
184
- >
185
- > 下一步指令:
186
- > `/glue-run-test <projectDir>/src/tests/<需求名>/testcase.json5`
187
-
188
- ## 6. 引导场景
189
-
190
- - **A(缺脚手架)**:Step 2 反查 projects.index.json5 无 glue 条目 → 提示先跑 `/glue-create-project` 退出。
191
- - **D(缺 code_list.json5)**:Step 3 缺失 → AskUserQuestion 三选一(提供路径 / 读 PRD 草稿 / 取消)。
192
- - **B / C**:由下游 `glue-run-test` 处理。
193
-
194
- ## 7. 输入字段约定
195
-
196
- ```markdown
197
- <!-- code_list.json5 字段约定(REQ-FILE-02 / REQ-MENU-01) -->
198
- knowledgeRoot: /abs/path/to/knowledge-project/xxx <!-- 推荐:结构化根目录 -->
199
-
200
- > 整理目录:`/abs/path/to/knowledge-project/xxx` <!-- 兼容旧格式;其余相对路径默认相对该目录 -->
201
- > 菜单:一级菜单>二级菜单 <!-- 人工读写首选:中文键「菜单」,与「整理目录」同风格;可选,缺时引导补,最终写入 testcase.json5.menuPath -->
202
- menu: 一级菜单>二级菜单 <!-- 英文键兼容:裸行 menu / menuPath 仍可解析(blockquote「>」形式仅认「菜单」)。CLI 内部字段名仍为 menu -->
203
-
204
- `_docs/.../spec.yaml`
205
- `src/main/webapp/.../*.html`
206
- `src/main/java/.../*Action.java`
207
-
208
- <!-- module-hints 是 CLI 基于上游物料推理的过程产物(落入 .ep-stage/inference-trace.json),
209
- 不是 code_list 该列的输入物料;旧 examples/zwplace.module-hints.json 仅作历史 fixture(REQ-INFER-010)。 -->
210
- ```
211
-
212
- ## 8. 内嵌数据契约范例
213
-
214
- `<需求名>/testcase.json5` 顶层骨架(v1-draft,详见 references/testcase-schema.md):
215
-
216
- ```json5
217
- {
218
- schemaVersion: "ep-stage-testcase/v1-draft",
219
- testcaseId: "zwplace-testcase",
220
- contractRef: ".ep-stage/contract.json5", // 指向同需求目录 .ep-stage/contract.json5
221
- scenario: "crud_export", // 产物:CLI 按 code_list.json5 推导,014 默认 crud_export
222
- moduleId: "zwplace", moduleName: "场所窗口信息管理",
223
- menuPath: "场所窗口信息管理>场所窗口信息列表",
224
- runtimeContext: {
225
- testProjectDir: "/abs/path/to/glue-project",
226
- caseDir: "/abs/path/to/glue-project/src/tests/014-测试需求10-20260622",
227
- specPath: "/abs/path/to/glue-project/src/tests/014-测试需求10-20260622/crud.spec.ts"
228
- },
229
- testAccess: {
230
- credentialRef: "credentials.json5",
231
- requiredRoles: ["业务管理员"]
232
- },
233
- cases: [
234
- { caseId: "zwplace-placename-create", title: "场所名称-新增", generationStrategy: "glue", coverageStatus: "covered", reviewStatus: "confirmed", queryKey: "场所名称", precondition: "使用具备权限的测试角色登录系统并进入目标列表页", steps: "按查询主键完成新增、查询、编辑、删除或导出流程", assertion: "按查询主键、列表结果或导出行为验证执行结果" }
235
- // cases[] 桶只承载 generationStrategy='glue';正式执行字段同步写入 queryKey/precondition/steps/assertion
236
- ],
237
- uncoveredCandidates: [
238
- { caseId: "businessState.transitions", label: "状态流转", generationStrategy: "ai", coverageStatus: "gap", requiredRole: "业务管理员", businessIntent: "覆盖在用不可删除等业务规则边界", assertionExpectation: "在用状态场所执行删除时应被业务规则阻断", queryKey: "不适用", precondition: "使用角色:业务管理员", steps: "按 AI Runtime Task 观察页面并执行:覆盖在用不可删除等业务规则边界", assertion: "在用状态场所执行删除时应被业务规则阻断" }
239
- // uncoveredCandidates[] 桶只承载 generationStrategy='ai';缺入口/缺权限/缺运行数据用 coverageStatus='blocked' 表达,同时保留正式执行字段
240
- ]
241
- }
242
- ```
243
-
244
- `<需求名>/credentials.template.json5`(按 code_list.json5 的业务角色事实生成模板) + `~/.ep-stage/projects.index.json5` 需求条目(CLI 追加到 `projects[].requirements[]`):
245
-
246
- ```json5
247
- // credentials.template.json5
248
- [
249
- {
250
- directUrl: "<请填待测页面直达链接,取 view-source: 后面的页面地址>",
251
- loginUrl: "<请填登录地址>",
252
- systemName: "<请填系统名称>",
253
- role: "业务管理员",
254
- username: "<请填账号>",
255
- password: "<请填密码>",
256
- },
257
- ]
258
-
259
- // projects.index.json5 → projects[].requirements[<i>]
260
- { name: "014-测试需求10-20260622", requirementDir: "/abs/.../014-测试需求10-20260622", testsDir: "<projectDir>/src/tests/014-测试需求10-20260622", lastRunStatus: "never" }
261
- ```
262
-
263
- ## 9. 按需加载
264
-
265
- - 用例 schema 详解:`references/testcase-schema.md`(v1-draft)
266
- - **testcase.md 渲染规则:统一单表,列为用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言**
267
- - 既有工作流参考:`references/workflow.md`
268
-
269
- ## 10. 关键约束
270
-
271
- - 顶层 `reviewStatus` 字段**永远不引入**(REQ-DATA-04);审阅意见请直接在 `testcase.json5` 加 JSON5 `// 注释`。
272
- - `cases[].reviewStatus = needs_review` 的用例不得进入 spec 组装(spec 组装阶段按 case 粒度阻断)。
273
- - 嵌套 CRUD 一期仅作为候选用例进入 testcase,不写入正式 CRUD 契约。
274
- - testcase.md 每次重跑完全覆盖,不保留人工编辑;事实源始终是 testcase.json5。审阅视图固定为统一单表,glue 与 ai 只通过“生成策略”列区分,不再拆成两个表。
275
- - 对话中展示可审阅推理摘要和证据链,不展示原始隐式思维链。
1
+ ---
2
+ name: glue-generate-testcase
3
+ description: 使用时机:当用户对某需求要「生成用例 / 准备测试场景 / 钻探上游需求生成胶水冒烟用例」或显式触发 `/glue-generate-testcase <code_list.json5路径>` 时使用。本 skill 包装 `@epoint-testtech/ep-stage-skill` CLI 的 `testcase` 子命令,并负责自然语言映射、缺数据引导、Step 5 凭据交互确认。
4
+ version: 2026-07-03+06ded5d
5
+ argument-hint: "<code_list.json5绝对/相对路径>"
6
+ ---
7
+
8
+ # ep-stage: glue-generate-testcase
9
+
10
+ 本 skill 引导 Agent **包装** `@epoint-testtech/ep-stage-skill` CLI 的 `testcase` 子命令,不重新实现钻探与用例生成。CLI 内部完成物料解析 + contract 提取(内嵌)+ coverage 分析 + testcase 装配 + credentials.template 生成。skill 负责:`code_list.json5` 路径解析、反查项目脚手架、缺数据引导、Step 5 平台对话确认凭据、审阅引导。用户视角全中文,不暴露 CLI 名称。
11
+
12
+ > **契约可观测性 gate**:每个非平凡字段必须能追溯到上游证据、可重复推导规则、运行配置来源或人工确认问题;无法给出来源的字段必须进入 `unresolvedSlots`,禁止写入 `contract.json5`。"无来源不入契约"。
13
+
14
+ > 钻探前置:testcase.json5 顶层(schemaVersion:'ep-stage-testcase/v1-draft' + testcaseId + contractRef + scenario + moduleId + moduleName + runtimeContext? + testAccess? + cases + uncoveredCandidates)由 CLI 一次写入。scenario 由 CLI 按 `code_list.json5` 推导(assembler),014 默认 `crud_export`;scenario 作为**产物**(非输入)写入顶层。`menuPath` 不是新链路必填字段。`runtimeContext` 用于落定工程与 spec 路径;`testAccess` 只保存 `credentialRef/requiredRoles`,明文账号密码与运行访问数据统一写入 `credentials.json5`。`directUrl` 是待测页面直达地址,不属于上游出码事实;缺失时必须在本 skill 交互补齐,并通过 CLI 参数写入 `contract.json5.base.navigation.directUrl`。**module-hints 已废弃**(交接文档 §4.1),不作为输入。
15
+
16
+ ## 1. 自然语言映射
17
+
18
+ ```text
19
+ /glue-generate-testcase /abs/path/.../014-测试需求10-20260622/_docs/code_list.json5 # 绝对路径
20
+ /glue-generate-testcase ../knowledge-project/.../014-测试需求10-20260622/_docs/code_list.json5 # 相对路径
21
+ /glue-generate-testcase # 无参数 → 问 code_list.json5 路径
22
+ /glue-generate-testcase /abs/path/.../014-测试需求10-20260622/_docs/code_list.json5 --debug # 调试模式 → 跑本地 ep-stage-skill dist
23
+ ```
24
+
25
+ > **`--debug` flag**:正常调用走远程 `npx @epoint-testtech/ep-stage-skill@latest`。开发期想测试未发布的本地代码时传 `--debug`,skill 在 Step 4 改用 `node <repo>/packages/ep-stage-skill/dist/src/cli/index.js`。前提:cwd 在 ep-stage monorepo 内(向上能找到 `pnpm-workspace.yaml`);找不到时直接 exit 1 报错,不静默 fallback 到 npx。
26
+
27
+ `--scenario` 不作为正常路径输入(scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`);`--hints` / module-hints 已废弃,不作为输入。
28
+
29
+ skill 把 `code_list.json5` 入参 `path.resolve` 绝对化,用其父目录的父目录 basename 取「需求名」作为 `<projectDir>/src/tests/<需求名>` 子目录(`_docs/code_list.json5` 上一级即需求目录)。**projectDir 不接受参数**,全部从 `~/.ep-stage/projects.index.json5` 反查最新 `mode: 'glue'` 条目(多条 AskUserQuestion 让用户挑);索引缺失走引导场景 A。
30
+
31
+ ## 2. Agent 执行剧本(8 步任务清单协议)
32
+
33
+ **任务清单协议(REQ-UX-01)**:load 后**立即**打印初始任务清单(Step 0);每完成一步输出单行 `第 N 步 — <中文名> 已完成,进入第 N+1 步 — <下一中文名>...`;Step 8 输出全勾选终态清单 + 摘要。
34
+
35
+ ### Step 0 — 打印任务清单
36
+
37
+ ```markdown
38
+ **生成胶水测试用例任务清单**
39
+
40
+ - [ ] 第 1 步 — 解析 code_list.json5 路径
41
+ - [ ] 第 2 步 — 反查项目脚手架
42
+ - [ ] 第 3 步 — 校验 code_list.json5 输入
43
+ - [ ] 第 4 步 — 补齐待测页面 directUrl 并调用钻探与用例生成 CLI
44
+ - [ ] 第 5 步 — 与研发人员交互确认推断结果
45
+ - [ ] 第 6 步 — 校验产物完整性 + 审阅 testcase.md 单表
46
+ - [ ] 第 7 步 — 写入需求条目到项目索引
47
+ - [ ] 第 8 步 — 输出审阅引导摘要
48
+ ```
49
+
50
+ ### Step 1 — 解析 code_list 路径
51
+
52
+ 从用户消息 / args 抽取 `code_list.json5` 路径,绝对化后得到 `codeListPath`,再用其父目录的父目录 basename 作为需求名(`_docs/code_list.json5` 上一级即需求目录)。中文复述识别结果:"已识别:code_list.json5 = `<abs>`,需求名 = `<basename>`"。入参缺失 → free text 询问"请给我 code_list.json5 的绝对或相对路径(位于需求目录 `_docs/` 下)"。
53
+
54
+ ### Step 2 — 反查项目脚手架(缺 → 引导 A)
55
+
56
+ 读 `~/.ep-stage/projects.index.json5`:文件不存在 / 无 glue 条目 → **引导场景 A**:中文提示"未发现胶水测试脚手架。请先跑 `/glue-create-project <项目名>` 创建脚手架后再回来",退出不调 CLI。多条匹配 → AskUserQuestion 挑 projectDir。单条 → 直接拼 `--tests-dir` 根。
57
+
58
+ ### Step 3 — 校验 code_list.json5 输入(缺 → 引导 D)
59
+
60
+ 校验 `codeListPath` 是否存在,且 `code_list.json5` 内至少给出:
61
+ - `knowledgeRoot: /abs/path`,或
62
+ - `> 整理目录:\`/abs/path\``
63
+
64
+ 其余物料路径默认视为相对该根目录的路径;若某项缺失或不存在,再进入交互补齐。`codeListPath` 本身缺失 → **引导场景 D**,AskUserQuestion 三选一:
65
+
66
+ 1. **提供 code_list.json5 路径**:让用户给绝对路径(位于需求目录 `_docs/` 下),skill 改用该路径继续。
67
+ 2. **读 PRD 草稿生成 code_list.json5**:在需求目录找 PRD / spec.yaml,AI 推断 `knowledgeRoot` / `menu` / 文件清单写一份 `code_list.json5` 草稿到 `_docs/` 下,提示"已生成草稿,请人审后再跑",退出。
68
+ 3. **取消**:直接退出,不调 CLI。
69
+
70
+ ### Step 4 — 补齐待测页面 directUrl 并调用钻探与用例生成 CLI
71
+
72
+ 固定流程(不 which、不扫 monorepo、不 cd、**不喂 stdin**)。调用 CLI 前先确定待测页面 `directUrl`:
73
+
74
+ - 若 `code_list.json5` 已有待测页面节点的 `pages[role=list].directUrl`,直接使用。
75
+ - 若缺失,必须用平台对话询问用户:"请提供待测页面直达链接(directUrl)。说明:直达链接通常来自浏览器地址栏中 view-source: 后面的页面地址;例如 view-source:http://192.168.203.46:8100/epoint-web/perpage/zwplace/gxhzwplacelist.html,实际填写 http://192.168.203.46:8100/epoint-web/perpage/zwplace/gxhzwplacelist.html。"
76
+ - 仍缺失则停止,不调 CLI。禁止让下游 `glue-run-test` 自行猜入口。
77
+
78
+ **正常模式**(用户 args 无 `--debug`):
79
+
80
+ ```bash
81
+ npx -y @epoint-testtech/ep-stage-skill@latest testcase \
82
+ --code-list <codeListPath> \
83
+ --tests-dir <projectDir>/src/tests/<需求名> \
84
+ --requirement-dir <codeListPath 的父目录> \
85
+ --project-dir <projectDir> \
86
+ --direct-url <待测列表页 directUrl>
87
+ ```
88
+
89
+ (scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`,正常路径不传 `--scenario`)
90
+
91
+ **调试模式**(用户 args 含 `--debug`,要求 cwd 在 ep-stage monorepo 内;详见 §1 `--debug` flag 说明):
92
+
93
+ ```bash
94
+ D="$PWD"; REPO=""
95
+ while [ "$D" != "/" ]; do
96
+ if [ -f "$D/pnpm-workspace.yaml" ] && [ -f "$D/packages/ep-stage-skill/dist/src/cli/index.js" ]; then
97
+ REPO="$D"; break
98
+ fi
99
+ D="$(dirname "$D")"
100
+ done
101
+ [ -z "$REPO" ] && { echo "错误:--debug 但找不到本地 monorepo(需 cwd 在 ep-stage 仓库内向上能找到 pnpm-workspace.yaml + packages/ep-stage-skill/dist/src/cli/index.js)"; exit 1; }
102
+ echo "调试模式:本地 $REPO/packages/ep-stage-skill/dist/src/cli/index.js"
103
+ node "$REPO/packages/ep-stage-skill/dist/src/cli/index.js" testcase \
104
+ --code-list <codeListPath> \
105
+ --tests-dir <projectDir>/src/tests/<需求名> \
106
+ --requirement-dir <codeListPath 的父目录> \
107
+ --project-dir <projectDir> \
108
+ --direct-url <待测列表页 directUrl>
109
+ ```
110
+
111
+ (scenario 由 CLI 按 `code_list.json5` 推导,014 默认 `crud_export`,正常路径不传 `--scenario`)
112
+
113
+ CLI 内部:按 `code_list.json5` 解析物料 → assembler 推导 scenario(014 默认 `crud_export`)→ 装配 contract + testcase(scenario 作为产物写入 `testcase.json5` 顶层,`directUrl` 写入 `contract.json5.base.navigation.directUrl`,`testcase.json5.testAccess` 只写 `credentialRef/requiredRoles`)→ schema 门禁 → 写 testcase.json5 / testcase.md(统一单表审阅视图)/ credentials.template.json5 / `.ep-stage/contract.json5` / `.ep-stage/inference-trace.json`。testcase.md 只渲染一张用例表,列为:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言。glue 与 ai 通过“生成策略”列区分,不拆成两个表。CLI 非 0 退出 → 复述 stderr,不发完成提示,不进 Step 5。
114
+
115
+ ### Step 5 — 与研发人员交互确认推断结果(REQ-UX-02)
116
+
117
+ Step 4 成功后,skill 读 CLI 产出的 `credentials.template.json5`(行数 = `code_list.roles.length`,每条对应一个角色)+ `uncoveredCandidates[].requiredRole`,再读 `~/.ep-stage/projects.index.json5` 的 `systems[]` 算 `cachedSystemsHit`(url 命中的列表)。用**平台对话能力**(Claude Code 用 `AskUserQuestion` / Codex 用对应交互机制)跟用户对话:
118
+
119
+ > 推断出 **N 个角色**(如 建设单位 / 施工单位 / 监理单位)。请选择:
120
+ > 1. **现在交互输入**(推荐:≤3 角色场景)— 我逐个角色问直达链接(directUrl)/ 登录地址(loginUrl)/ 系统名称(systemName)/ 角色(role)/ 账号(username)/ 密码(password),汇总摘要请你确认后写 `credentials.json5`
121
+ > 2. **仅生成 template,自己后续填** — 退出后请拷贝 `credentials.template.json5` → `credentials.json5` 并填值
122
+ > 3. **跳过,使用全局 systems[] 缓存复用** — 自动从 `cachedSystemsHit` 命中缓存生成 `credentials.json5`(缺失角色 fallback 引导 C,留给 glue-run-test)
123
+
124
+ 三分支处理:
125
+
126
+ - **选 1**:skill 顺序问每条角色的直达链接(directUrl)/ 登录地址(loginUrl)/ 系统名称(systemName)/ 角色(role)/ 账号(username)/ 密码(password)(free text)。直达链接问题必须说明其来源是 `view-source:` 后面的页面地址。收集后先展示摘要给用户确认;确认后写 `<需求名>/credentials.json5`(gitignore,非 template),`<需求名>/testcase.json5.testAccess` 只保留 `credentialRef: 'credentials.json5'` 和 `requiredRoles`,**回写**全局 `~/.ep-stage/projects.index.json5` 的 `systems[].credentialsCache`(按 loginUrl 归并,跨需求复用)。
127
+ - **选 2**:保留 template;提示"请编辑 `credentials.json5` 后再跑 `/glue-run-test`",进入 Step 6。
128
+ - **选 3**:从 `systems[].credentialsCache` 拼出 credentials.json5,缺失角色用 template 占位符保留;`<需求名>/testcase.json5.testAccess` 只保留 `credentialRef: 'credentials.json5'` 和 `requiredRoles`,不写明文账号密码。
129
+
130
+ ### Step 6 — 校验产物完整性 + 审阅 testcase.md 单表
131
+
132
+ **Step 6.1 — 校验产物完整性**
133
+
134
+ 按 §3 验证清单 `ls` / `Read` 校验 CLI 产物存在(除 `testcase.md` 外其他全部,缺任意一项视为整体失败,按 §4 报告):
135
+
136
+ - `testcase.json5`、`credentials.template.json5`(或 `credentials.json5`)、`.ep-stage/contract.json5`、`.ep-stage/inference-trace.json`
137
+
138
+ Step 6 只需要确认 CLI 已基于 `testcase.json5` 事实源写出 `testcase.md`。该文件固定是一张审阅表,列为:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言。glue 与 ai 统一在同一张表中,通过“生成策略”列区分。每次重跑都会整体覆盖 `testcase.md`;人审意见只写进 `testcase.json5`(JSON5 `// 注释`),不写 `testcase.md`。
139
+
140
+ ### Step 7 — 写入需求条目到项目索引
141
+
142
+ CLI testcase 子命令在传入 `--project-dir` 时,自动往 `~/.ep-stage/projects.index.json5` 对应 `projects[].requirements[]` 追加本需求条目(含 `name / requirementDir / testsDir / lastRunStatus: "never"`,同名需求去重更新);未传 `--project-dir` 则跳过(不维护 index)。skill Step 4 命令总带 `--project-dir`,故正常流程 CLI 必追加。skill 校验:条目存在;`name` 与 Step 1 一致;`testsDir` 指向 `<projectDir>/src/tests/<需求名>`。
143
+
144
+ ### Step 8 — 输出审阅引导摘要
145
+
146
+ 打印全勾选终态清单 + §5 完成提示(含审阅引导链:审 testcase.md → 编辑 testcase.json5 → 填 credentials.json5 → 跑 `/glue-run-test`)。
147
+
148
+ ## 3. 验证清单
149
+
150
+ | 路径 | 说明 |
151
+ |--------------------------------------------------------------|--------------------------------------------------------|
152
+ | `<projectDir>/src/tests/<需求名>/testcase.json5` | testcase schema v1-draft(schemaVersion / scenario / moduleId / moduleName / menuPath / runtimeContext? / testAccess? / contractRef / cases / uncoveredCandidates),**事实源** |
153
+ | `<projectDir>/src/tests/<需求名>/testcase.md` | 基于 `testcase.json5` 渲染的单表审阅视图(列:用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言;重跑覆盖) |
154
+ | `<projectDir>/src/tests/<需求名>/credentials.template.json5` | 行数 = `code_list.roles.length`(每条对应一个角色) |
155
+ | `<projectDir>/src/tests/<需求名>/.ep-stage/contract.json5` | 内部产物,机器专用,禁手编 |
156
+ | `<projectDir>/src/tests/<需求名>/.ep-stage/inference-trace.json` | 推理追踪总账,只供排查和审阅,不作为 spec 主输入 |
157
+ | `~/.ep-stage/projects.index.json5` | 已追加 `projects[].requirements[]` |
158
+
159
+ > 常态不生成 `source-spec.json` 或 `module-hints.inferred.json5`;二者只作为显式调试导出,非正常产物。
160
+
161
+ ## 4. 错误处理
162
+
163
+ | 触发时机 | Agent 中文呈现 + 建议 |
164
+ |-----------------------------------------|----------------------------------------------------------------------|
165
+ | 引导 A(缺脚手架) | 中文提示+退出,引导先跑 `/glue-create-project` |
166
+ | 引导 D(缺 code_list.json5) | AskUserQuestion 三选一:提供路径 / 读 PRD 草稿 / 取消 |
167
+ | CLI exit ≠ 0 | 复述 stderr 中文转述,不发完成提示,不进 Step 5 |
168
+ | testcase.json5 缺 `schemaVersion` | 报"产物 schema 校验失败,请重跑 `/glue-generate-testcase <code_list.json5路径>`" |
169
+ | Step 5 选 1 用户中途取消 | 保留 template,提示"凭据未写入,请稍后拷贝 template 自填" |
170
+ | testcase.md 单表缺失或结构异常 | 复述缺失项或列结构异常,提示检查 testcase.json5 与 CLI 输出后重跑 |
171
+
172
+ ## 5. 完成提示
173
+
174
+ Step 8 全部通过后,按以下中文格式呈现(不要用 success/done/generated):
175
+
176
+ > 用例已生成。
177
+ >
178
+ > 测试项目:`<projectDir>`
179
+ > 用例文件:`<projectDir>/src/tests/<需求名>/testcase.json5`
180
+ > 用例摘要:共 N 条,胶水组装 X 条,AI 推理 Y 条
181
+ > 重点审核:AI 推理用例、blocked 候选、登录角色信息
182
+ >
183
+ > 需要调整的话,直接告诉我改哪条用例,我来更新 testcase.json5。
184
+ >
185
+ > 下一步指令:
186
+ > `/glue-run-test <projectDir>/src/tests/<需求名>/testcase.json5`
187
+
188
+ ## 6. 引导场景
189
+
190
+ - **A(缺脚手架)**:Step 2 反查 projects.index.json5 无 glue 条目 → 提示先跑 `/glue-create-project` 退出。
191
+ - **D(缺 code_list.json5)**:Step 3 缺失 → AskUserQuestion 三选一(提供路径 / 读 PRD 草稿 / 取消)。
192
+ - **B / C**:由下游 `glue-run-test` 处理。
193
+
194
+ ## 7. 输入字段约定
195
+
196
+ ```markdown
197
+ <!-- code_list.json5 字段约定(REQ-FILE-02 / REQ-MENU-01) -->
198
+ knowledgeRoot: /abs/path/to/knowledge-project/xxx <!-- 推荐:结构化根目录 -->
199
+
200
+ > 整理目录:`/abs/path/to/knowledge-project/xxx` <!-- 兼容旧格式;其余相对路径默认相对该目录 -->
201
+ > 菜单:一级菜单>二级菜单 <!-- 人工读写首选:中文键「菜单」,与「整理目录」同风格;可选,缺时引导补,最终写入 testcase.json5.menuPath -->
202
+ menu: 一级菜单>二级菜单 <!-- 英文键兼容:裸行 menu / menuPath 仍可解析(blockquote「>」形式仅认「菜单」)。CLI 内部字段名仍为 menu -->
203
+
204
+ `_docs/.../spec.yaml`
205
+ `src/main/webapp/.../*.html`
206
+ `src/main/java/.../*Action.java`
207
+
208
+ <!-- module-hints 是 CLI 基于上游物料推理的过程产物(落入 .ep-stage/inference-trace.json),
209
+ 不是 code_list 该列的输入物料;旧 examples/zwplace.module-hints.json 仅作历史 fixture(REQ-INFER-010)。 -->
210
+ ```
211
+
212
+ ## 8. 内嵌数据契约范例
213
+
214
+ `<需求名>/testcase.json5` 顶层骨架(v1-draft,详见 references/testcase-schema.md):
215
+
216
+ ```json5
217
+ {
218
+ schemaVersion: "ep-stage-testcase/v1-draft",
219
+ testcaseId: "zwplace-testcase",
220
+ contractRef: ".ep-stage/contract.json5", // 指向同需求目录 .ep-stage/contract.json5
221
+ scenario: "crud_export", // 产物:CLI 按 code_list.json5 推导,014 默认 crud_export
222
+ moduleId: "zwplace", moduleName: "场所窗口信息管理",
223
+ menuPath: "场所窗口信息管理>场所窗口信息列表",
224
+ runtimeContext: {
225
+ testProjectDir: "/abs/path/to/glue-project",
226
+ caseDir: "/abs/path/to/glue-project/src/tests/014-测试需求10-20260622",
227
+ specPath: "/abs/path/to/glue-project/src/tests/014-测试需求10-20260622/crud.spec.ts"
228
+ },
229
+ testAccess: {
230
+ credentialRef: "credentials.json5",
231
+ requiredRoles: ["业务管理员"]
232
+ },
233
+ cases: [
234
+ { caseId: "zwplace-placename-create", title: "场所名称-新增", generationStrategy: "glue", coverageStatus: "covered", reviewStatus: "confirmed", queryKey: "场所名称", precondition: "使用具备权限的测试角色登录系统并进入目标列表页", steps: "按查询主键完成新增、查询、编辑、删除或导出流程", assertion: "按查询主键、列表结果或导出行为验证执行结果" }
235
+ // cases[] 桶只承载 generationStrategy='glue';正式执行字段同步写入 queryKey/precondition/steps/assertion
236
+ ],
237
+ uncoveredCandidates: [
238
+ { caseId: "businessState.transitions", label: "状态流转", generationStrategy: "ai", coverageStatus: "gap", requiredRole: "业务管理员", businessIntent: "覆盖在用不可删除等业务规则边界", assertionExpectation: "在用状态场所执行删除时应被业务规则阻断", queryKey: "不适用", precondition: "使用角色:业务管理员", steps: "按 AI Runtime Task 观察页面并执行:覆盖在用不可删除等业务规则边界", assertion: "在用状态场所执行删除时应被业务规则阻断" }
239
+ // uncoveredCandidates[] 桶只承载 generationStrategy='ai';缺入口/缺权限/缺运行数据用 coverageStatus='blocked' 表达,同时保留正式执行字段
240
+ ]
241
+ }
242
+ ```
243
+
244
+ `<需求名>/credentials.template.json5`(按 code_list.json5 的业务角色事实生成模板) + `~/.ep-stage/projects.index.json5` 需求条目(CLI 追加到 `projects[].requirements[]`):
245
+
246
+ ```json5
247
+ // credentials.template.json5
248
+ [
249
+ {
250
+ directUrl: "<请填待测页面直达链接,取 view-source: 后面的页面地址>",
251
+ loginUrl: "<请填登录地址>",
252
+ systemName: "<请填系统名称>",
253
+ role: "业务管理员",
254
+ username: "<请填账号>",
255
+ password: "<请填密码>",
256
+ },
257
+ ]
258
+
259
+ // projects.index.json5 → projects[].requirements[<i>]
260
+ { name: "014-测试需求10-20260622", requirementDir: "/abs/.../014-测试需求10-20260622", testsDir: "<projectDir>/src/tests/014-测试需求10-20260622", lastRunStatus: "never" }
261
+ ```
262
+
263
+ ## 9. 按需加载
264
+
265
+ - 用例 schema 详解:`references/testcase-schema.md`(v1-draft)
266
+ - **testcase.md 渲染规则:统一单表,列为用例 ID / 生成策略 / 用例标题 / 查询主键 / 前置条件 / 执行步骤 / 执行断言**
267
+ - 既有工作流参考:`references/workflow.md`
268
+
269
+ ## 10. 关键约束
270
+
271
+ - 顶层 `reviewStatus` 字段**永远不引入**(REQ-DATA-04);审阅意见请直接在 `testcase.json5` 加 JSON5 `// 注释`。
272
+ - `cases[].reviewStatus = needs_review` 的用例不得进入 spec 组装(spec 组装阶段按 case 粒度阻断)。
273
+ - 嵌套 CRUD 一期仅作为候选用例进入 testcase,不写入正式 CRUD 契约。
274
+ - testcase.md 每次重跑完全覆盖,不保留人工编辑;事实源始终是 testcase.json5。审阅视图固定为统一单表,glue 与 ai 只通过“生成策略”列区分,不再拆成两个表。
275
+ - 对话中展示可审阅推理摘要和证据链,不展示原始隐式思维链。