@epoint-testtech/ep-stage-skill 0.0.3-alpha.2 → 0.0.4-alpha.1

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 (155) hide show
  1. package/SKILL.md +2 -2
  2. package/codex-skill/ep-stage/.omc/state/sessions/d636ad35-5fc9-4d5e-85b0-2bcad7d86ee5/pre-tool-advisory-throttle.json +10 -0
  3. package/codex-skill/ep-stage/glue-create-project/SKILL.md +206 -0
  4. package/codex-skill/ep-stage/glue-generate-testcase/SKILL.md +274 -0
  5. package/codex-skill/ep-stage/glue-generate-testcase/references/testcase-schema.md +112 -0
  6. package/codex-skill/ep-stage/glue-generate-testcase/references/testcase-tpl.md +72 -0
  7. package/codex-skill/ep-stage/glue-run-test/SKILL.md +289 -0
  8. package/codex-skill/ep-stage/glue-run-test/references/crud-pipeline.md +145 -0
  9. package/codex-skill/ep-stage/{glue-test → glue-run-test}/scripts/generate-crud-spec.mjs +3 -3
  10. package/codex-skill/ep-stage/recording-to-glue/SKILL.md +1 -0
  11. package/codex-skill/ep-stage/scripts/validate-skill.mjs +29 -7
  12. package/dist/src/cli/dev/extract-contract.d.ts +14 -0
  13. package/dist/src/cli/dev/extract-contract.d.ts.map +1 -0
  14. package/dist/src/cli/dev/extract-contract.js +114 -0
  15. package/dist/src/cli/generate-crud-contract.js +7 -77
  16. package/dist/src/cli/generate-playwright-tests.d.ts +0 -28
  17. package/dist/src/cli/generate-playwright-tests.d.ts.map +1 -1
  18. package/dist/src/cli/generate-playwright-tests.js +4 -81
  19. package/dist/src/cli/generate-testcase.d.ts +84 -0
  20. package/dist/src/cli/generate-testcase.d.ts.map +1 -0
  21. package/dist/src/cli/generate-testcase.js +300 -0
  22. package/dist/src/cli/index.d.ts +26 -0
  23. package/dist/src/cli/index.d.ts.map +1 -0
  24. package/dist/src/cli/index.js +75 -0
  25. package/dist/src/cli/probe.d.ts +46 -0
  26. package/dist/src/cli/probe.d.ts.map +1 -0
  27. package/dist/src/cli/probe.js +447 -0
  28. package/dist/src/cli/run-gap-pipeline.js +4 -0
  29. package/dist/src/cli/run.d.ts +63 -0
  30. package/dist/src/cli/run.d.ts.map +1 -0
  31. package/dist/src/cli/run.js +116 -0
  32. package/dist/src/cli/spec.d.ts +48 -0
  33. package/dist/src/cli/spec.d.ts.map +1 -0
  34. package/dist/src/cli/spec.js +102 -0
  35. package/dist/src/context/stage-context.d.ts +72 -8
  36. package/dist/src/context/stage-context.d.ts.map +1 -1
  37. package/dist/src/context/stage-context.js +61 -15
  38. package/dist/src/contracts/inference-trace.d.ts +223 -0
  39. package/dist/src/contracts/inference-trace.d.ts.map +1 -0
  40. package/dist/src/contracts/inference-trace.js +12 -0
  41. package/dist/src/extractors/code-list.d.ts +3 -3
  42. package/dist/src/extractors/code-list.d.ts.map +1 -1
  43. package/dist/src/extractors/code-list.js +46 -11
  44. package/dist/src/generators/stage-skeleton-script.d.ts.map +1 -1
  45. package/dist/src/generators/stage-skeleton-script.js +9 -0
  46. package/dist/src/index.d.ts +7 -2
  47. package/dist/src/index.d.ts.map +1 -1
  48. package/dist/src/index.js +3 -1
  49. package/dist/src/inference/module-hints-inference.d.ts +30 -0
  50. package/dist/src/inference/module-hints-inference.d.ts.map +1 -0
  51. package/dist/src/inference/module-hints-inference.js +363 -0
  52. package/dist/src/inference/source-analysis.d.ts +26 -0
  53. package/dist/src/inference/source-analysis.d.ts.map +1 -0
  54. package/dist/src/inference/source-analysis.js +258 -0
  55. package/dist/src/testcase/testcase-generator.d.ts.map +1 -1
  56. package/dist/src/testcase/testcase-generator.js +4 -0
  57. package/dist/src/testcase/testcase-v2.d.ts +50 -0
  58. package/dist/src/testcase/testcase-v2.d.ts.map +1 -0
  59. package/dist/src/testcase/testcase-v2.js +1 -0
  60. package/dist/src/util/credentials.d.ts +12 -0
  61. package/dist/src/util/credentials.d.ts.map +1 -0
  62. package/dist/src/util/credentials.js +19 -0
  63. package/dist/src/util/i18n-testcase.d.ts +8 -0
  64. package/dist/src/util/i18n-testcase.d.ts.map +1 -0
  65. package/dist/src/util/i18n-testcase.js +55 -0
  66. package/dist/src/util/softlink.d.ts +33 -0
  67. package/dist/src/util/softlink.d.ts.map +1 -0
  68. package/dist/src/util/softlink.js +43 -0
  69. package/dist/src/validation/credentials.d.ts +19 -0
  70. package/dist/src/validation/credentials.d.ts.map +1 -0
  71. package/dist/src/validation/credentials.js +38 -0
  72. package/dist/src/validation/index.d.ts +6 -0
  73. package/dist/src/validation/index.d.ts.map +1 -0
  74. package/dist/src/validation/index.js +4 -0
  75. package/dist/src/validation/inference-trace.d.ts +13 -0
  76. package/dist/src/validation/inference-trace.d.ts.map +1 -0
  77. package/dist/src/validation/inference-trace.js +31 -0
  78. package/dist/src/validation/projects-index.d.ts +13 -0
  79. package/dist/src/validation/projects-index.d.ts.map +1 -0
  80. package/dist/src/validation/projects-index.js +37 -0
  81. package/dist/src/validation/testcase.d.ts +13 -0
  82. package/dist/src/validation/testcase.d.ts.map +1 -0
  83. package/dist/src/validation/testcase.js +53 -0
  84. package/dist/test/cli/extract-contract.test.d.ts +2 -0
  85. package/dist/test/cli/extract-contract.test.d.ts.map +1 -0
  86. package/dist/test/cli/extract-contract.test.js +32 -0
  87. package/dist/test/cli/generate-testcase-inference.test.d.ts +2 -0
  88. package/dist/test/cli/generate-testcase-inference.test.d.ts.map +1 -0
  89. package/dist/test/cli/generate-testcase-inference.test.js +63 -0
  90. package/dist/test/cli/generate-testcase-paths.test.d.ts +2 -0
  91. package/dist/test/cli/generate-testcase-paths.test.d.ts.map +1 -0
  92. package/dist/test/cli/generate-testcase-paths.test.js +165 -0
  93. package/dist/test/cli/generate-testcase-requirements.test.d.ts +2 -0
  94. package/dist/test/cli/generate-testcase-requirements.test.d.ts.map +1 -0
  95. package/dist/test/cli/generate-testcase-requirements.test.js +229 -0
  96. package/dist/test/cli/generate-testcase.test.d.ts +2 -0
  97. package/dist/test/cli/generate-testcase.test.d.ts.map +1 -0
  98. package/dist/test/cli/generate-testcase.test.js +130 -0
  99. package/dist/test/cli/index.test.d.ts +2 -0
  100. package/dist/test/cli/index.test.d.ts.map +1 -0
  101. package/dist/test/cli/index.test.js +113 -0
  102. package/dist/test/cli/probe.test.d.ts +2 -0
  103. package/dist/test/cli/probe.test.d.ts.map +1 -0
  104. package/dist/test/cli/probe.test.js +31 -0
  105. package/dist/test/cli/run.test.d.ts +2 -0
  106. package/dist/test/cli/run.test.d.ts.map +1 -0
  107. package/dist/test/cli/run.test.js +149 -0
  108. package/dist/test/cli/spec-boundary.test.d.ts +2 -0
  109. package/dist/test/cli/spec-boundary.test.d.ts.map +1 -0
  110. package/dist/test/cli/spec-boundary.test.js +198 -0
  111. package/dist/test/cli/spec.test.d.ts +2 -0
  112. package/dist/test/cli/spec.test.d.ts.map +1 -0
  113. package/dist/test/cli/spec.test.js +196 -0
  114. package/dist/test/code-list.test.d.ts +2 -0
  115. package/dist/test/code-list.test.d.ts.map +1 -0
  116. package/dist/test/code-list.test.js +39 -0
  117. package/dist/test/crud-contract.test.js +12 -32
  118. package/dist/test/inference/module-hints-inference.test.d.ts +2 -0
  119. package/dist/test/inference/module-hints-inference.test.d.ts.map +1 -0
  120. package/dist/test/inference/module-hints-inference.test.js +25 -0
  121. package/dist/test/inference/source-analysis.test.d.ts +2 -0
  122. package/dist/test/inference/source-analysis.test.d.ts.map +1 -0
  123. package/dist/test/inference/source-analysis.test.js +23 -0
  124. package/dist/test/material-inventory.test.js +13 -0
  125. package/dist/test/observable-pipeline.test.js +12 -3
  126. package/dist/test/stage-context.test.js +145 -13
  127. package/dist/test/util/credentials.test.d.ts +2 -0
  128. package/dist/test/util/credentials.test.d.ts.map +1 -0
  129. package/dist/test/util/credentials.test.js +64 -0
  130. package/dist/test/util/i18n-testcase.test.d.ts +2 -0
  131. package/dist/test/util/i18n-testcase.test.d.ts.map +1 -0
  132. package/dist/test/util/i18n-testcase.test.js +119 -0
  133. package/dist/test/util/softlink.test.d.ts +2 -0
  134. package/dist/test/util/softlink.test.d.ts.map +1 -0
  135. package/dist/test/util/softlink.test.js +82 -0
  136. package/dist/test/validation/credentials.test.d.ts +2 -0
  137. package/dist/test/validation/credentials.test.d.ts.map +1 -0
  138. package/dist/test/validation/credentials.test.js +72 -0
  139. package/dist/test/validation/projects-index.test.d.ts +2 -0
  140. package/dist/test/validation/projects-index.test.d.ts.map +1 -0
  141. package/dist/test/validation/projects-index.test.js +48 -0
  142. package/dist/test/validation/testcase.test.d.ts +2 -0
  143. package/dist/test/validation/testcase.test.d.ts.map +1 -0
  144. package/dist/test/validation/testcase.test.js +129 -0
  145. package/docs/README.md +6 -6
  146. package/docs/mvp-usage-guide.md +3 -3
  147. package/package.json +9 -4
  148. package/codex-skill/ep-stage/create-project/SKILL.md +0 -59
  149. package/codex-skill/ep-stage/glue-test/SKILL.md +0 -258
  150. package/codex-skill/ep-stage/glue-test/references/crud-pipeline.md +0 -139
  151. package/codex-skill/ep-stage/glue-testcase/SKILL.md +0 -31
  152. package/codex-skill/ep-stage/glue-testcase/references/testcase-schema.md +0 -67
  153. /package/codex-skill/ep-stage/{glue-testcase → glue-generate-testcase}/examples/observable-testcase.json +0 -0
  154. /package/codex-skill/ep-stage/{glue-test → glue-run-test}/references/gap-review-protocol.md +0 -0
  155. /package/codex-skill/ep-stage/{glue-test → glue-run-test}/references/harness-principles.md +0 -0
@@ -0,0 +1,48 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateProjectsIndex } from '../../src/validation/projects-index.js';
3
+ describe('validateProjectsIndex', () => {
4
+ it('通过合法结构(含 systems[] 与 stageCreateVersion)', () => {
5
+ const obj = {
6
+ projects: [
7
+ {
8
+ projectName: 'demo',
9
+ projectDir: '/abs/demo',
10
+ mode: 'glue',
11
+ createdAt: '2026-06-25T00:00:00Z',
12
+ stageCreateVersion: '0.0.4-alpha.0',
13
+ requirements: [],
14
+ },
15
+ ],
16
+ systems: [],
17
+ };
18
+ const result = validateProjectsIndex(obj);
19
+ expect(result.projects).toHaveLength(1);
20
+ expect(result.projects[0].stageCreateVersion).toBe('0.0.4-alpha.0');
21
+ expect(result.systems).toEqual([]);
22
+ });
23
+ it('缺 systems 字段时报结构化错误', () => {
24
+ expect(() => validateProjectsIndex({ projects: [] })).toThrow(/systems/);
25
+ });
26
+ it('项目条目缺 stageCreateVersion 报错(stage-context.md 砍掉后的元信息承接)', () => {
27
+ expect(() => validateProjectsIndex({
28
+ projects: [{ projectName: 'x', projectDir: '/x', mode: 'glue', requirements: [] }],
29
+ systems: [],
30
+ })).toThrow(/stageCreateVersion/);
31
+ });
32
+ it('不允许残留 stageContextPath / envPath / knowledgeRoot 字段', () => {
33
+ expect(() => validateProjectsIndex({
34
+ projects: [
35
+ {
36
+ projectName: 'x',
37
+ projectDir: '/x',
38
+ mode: 'glue',
39
+ createdAt: '2026-06-25T00:00:00Z',
40
+ stageCreateVersion: '0.0.4-alpha.0',
41
+ requirements: [],
42
+ stageContextPath: '/x/stage-context.md', // 应被拒绝
43
+ },
44
+ ],
45
+ systems: [],
46
+ })).toThrow(/stageContextPath|removed/);
47
+ });
48
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=testcase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testcase.test.d.ts","sourceRoot":"","sources":["../../../test/validation/testcase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateTestcase } from '../../src/validation/testcase.js';
3
+ /**
4
+ * 构造一份满足 v2 schema 的最小合法 testcase(REQ-DATA-02)。
5
+ *
6
+ * @returns 合法 testcase v2 对象。
7
+ */
8
+ function makeValidTestcase() {
9
+ return {
10
+ schemaVersion: 'v2',
11
+ scenario: '组织管理 CRUD 主流程',
12
+ moduleId: 'org-management',
13
+ moduleName: '组织管理',
14
+ menuPath: '系统管理 > 组织管理',
15
+ requiredSystems: [{ url: 'http://example.test', systemName: '基础平台' }],
16
+ requiredRoles: [{ role: '系统管理员', hint: '可访问组织管理菜单' }],
17
+ coveredActions: [
18
+ { actionId: 'create', kind: 'create', evidence: ['html=org-list.html#btn-add'] },
19
+ ],
20
+ uncoveredCandidates: [
21
+ {
22
+ actionId: 'export',
23
+ label: '导出',
24
+ status: 'planned',
25
+ requiredRole: '系统管理员',
26
+ businessIntent: '导出当前查询结果',
27
+ assertionExpectation: '断言下载文件存在',
28
+ evidence: ['hint=ModuleHints.export'],
29
+ },
30
+ ],
31
+ cases: [
32
+ {
33
+ caseId: 'CASE-001',
34
+ title: '管理员新增组织',
35
+ scenario: '组织管理 CRUD 主流程',
36
+ reviewStatus: 'confirmed',
37
+ requiredRole: '系统管理员',
38
+ evidence: ['spec=org-management.spec.yaml#create'],
39
+ steps: ['打开菜单', '点击新增'],
40
+ assertions: ['列表出现新组织'],
41
+ unresolved: [],
42
+ },
43
+ ],
44
+ reasoningSummary: {
45
+ conclusion: '主流程覆盖增删改查',
46
+ evidenceChain: ['html=org-list.html'],
47
+ alternatives: [],
48
+ confidence: 'high',
49
+ risks: [],
50
+ needsHumanReview: false,
51
+ },
52
+ };
53
+ }
54
+ describe('validateTestcase', () => {
55
+ it('合法 v2 testcase 通过', () => {
56
+ const result = validateTestcase(makeValidTestcase());
57
+ expect(result.schemaVersion).toBe('v2');
58
+ expect(result.cases).toHaveLength(1);
59
+ });
60
+ it('缺 schemaVersion 报版本错误引导重跑(v1 升级路径)', () => {
61
+ const tc = makeValidTestcase();
62
+ delete tc.schemaVersion;
63
+ expect(() => validateTestcase(tc)).toThrow(/schemaVersion|v2|重跑/);
64
+ });
65
+ it('schemaVersion 非 v2(视作 v1)也走版本错误引导重跑', () => {
66
+ const tc = { ...makeValidTestcase(), schemaVersion: 'v1' };
67
+ expect(() => validateTestcase(tc)).toThrow(/schemaVersion|v2|重跑/);
68
+ });
69
+ it('缺 scenario 报错', () => {
70
+ const tc = makeValidTestcase();
71
+ delete tc.scenario;
72
+ expect(() => validateTestcase(tc)).toThrow(/scenario/);
73
+ });
74
+ it('缺 menuPath 报错', () => {
75
+ const tc = makeValidTestcase();
76
+ delete tc.menuPath;
77
+ expect(() => validateTestcase(tc)).toThrow(/menuPath/);
78
+ });
79
+ it('缺 requiredSystems[] 报错', () => {
80
+ const tc = makeValidTestcase();
81
+ delete tc.requiredSystems;
82
+ expect(() => validateTestcase(tc)).toThrow(/requiredSystems/);
83
+ });
84
+ it('缺 requiredRoles[] 报错', () => {
85
+ const tc = makeValidTestcase();
86
+ delete tc.requiredRoles;
87
+ expect(() => validateTestcase(tc)).toThrow(/requiredRoles/);
88
+ });
89
+ it('缺 coveredActions[] 报错', () => {
90
+ const tc = makeValidTestcase();
91
+ delete tc.coveredActions;
92
+ expect(() => validateTestcase(tc)).toThrow(/coveredActions/);
93
+ });
94
+ it('缺 uncoveredCandidates[] 报错', () => {
95
+ const tc = makeValidTestcase();
96
+ delete tc.uncoveredCandidates;
97
+ expect(() => validateTestcase(tc)).toThrow(/uncoveredCandidates/);
98
+ });
99
+ it('uncoveredCandidates[].requiredRole 缺失报错', () => {
100
+ const tc = makeValidTestcase();
101
+ const uncovered = tc.uncoveredCandidates;
102
+ delete uncovered[0].requiredRole;
103
+ expect(() => validateTestcase(tc)).toThrow(/uncoveredCandidates.*requiredRole/);
104
+ });
105
+ it('coveredActions[].evidence 非 <kind>=<ref> 报错', () => {
106
+ const tc = makeValidTestcase();
107
+ const covered = tc.coveredActions;
108
+ covered[0].evidence = ['某条非法 evidence 字符串'];
109
+ expect(() => validateTestcase(tc)).toThrow(/evidence/);
110
+ });
111
+ it('uncoveredCandidates[].evidence 非 <kind>=<ref> 报错', () => {
112
+ const tc = makeValidTestcase();
113
+ const uncovered = tc.uncoveredCandidates;
114
+ uncovered[0].evidence = ['plainstring'];
115
+ expect(() => validateTestcase(tc)).toThrow(/evidence/);
116
+ });
117
+ it('cases[].evidence 非 <kind>=<ref> 报错', () => {
118
+ const tc = makeValidTestcase();
119
+ const cases = tc.cases;
120
+ cases[0].evidence = ['noequalsign'];
121
+ expect(() => validateTestcase(tc)).toThrow(/evidence/);
122
+ });
123
+ it('evidence kind 必须在 html/java/spec/contract/skeleton/hint 范围内', () => {
124
+ const tc = makeValidTestcase();
125
+ const covered = tc.coveredActions;
126
+ covered[0].evidence = ['unknownkind=foo.html'];
127
+ expect(() => validateTestcase(tc)).toThrow(/evidence/);
128
+ });
129
+ });
package/docs/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @epoint/ep-stage-skill
1
+ # @epoint-testtech/ep-stage-skill
2
2
 
3
3
  > 胶水编码链路 Agent Skill — 解析上游物料,按契约生成可执行测试脚本
4
4
 
@@ -11,8 +11,8 @@
11
11
  AI Agent 可发现的 Skill 入口(Claude Code 扫 `.claude/skills/`、Codex 扫 `.agents/skills/`,均 symlink 到包内源):
12
12
 
13
13
  ```text
14
- .claude/skills/{glue-test, create-project, recording-to-glue}
15
- .agents/skills/{glue-test, create-project, recording-to-glue}
14
+ .claude/skills/{glue-create-project, glue-generate-testcase, glue-run-test, recording-to-glue}
15
+ .agents/skills/{glue-create-project, glue-generate-testcase, glue-run-test, recording-to-glue}
16
16
  → packages/ep-stage-skill/codex-skill/ep-stage/<skill>/
17
17
  ```
18
18
 
@@ -31,11 +31,11 @@ AI Agent 可发现的 Skill 入口(Claude Code 扫 `.claude/skills/`、Codex
31
31
 
32
32
  ```bash
33
33
  # 可观测默认入口(推荐)
34
- pnpm --filter @epoint/ep-stage-skill run:gap-pipeline -- \
34
+ pnpm --filter @epoint-testtech/ep-stage-skill run:gap-pipeline -- \
35
35
  --code-list <code_list.md>
36
36
 
37
37
  # 生成契约
38
- pnpm --filter @epoint/ep-stage-skill generate:crud-contract -- \
38
+ pnpm --filter @epoint-testtech/ep-stage-skill generate:crud-contract -- \
39
39
  --module-id <模块ID> \
40
40
  --docs <上游文档目录> \
41
41
  --code-list <code_list.md> \
@@ -45,7 +45,7 @@ pnpm --filter @epoint/ep-stage-skill generate:crud-contract -- \
45
45
  --out output/<module>.crud.contract.json
46
46
 
47
47
  # 生成测试脚本
48
- pnpm --filter @epoint/ep-stage-skill generate:playwright-tests -- \
48
+ pnpm --filter @epoint-testtech/ep-stage-skill generate:playwright-tests -- \
49
49
  --contract output/<module>.crud.contract.json \
50
50
  --out <glue项目>/src/tests/<name>.spec.ts \
51
51
  --menu "一级菜单>二级菜单" \
@@ -1,8 +1,8 @@
1
- # glue-test CRUD 契约生成器 — MVP 使用手册
1
+ # glue-run-test CRUD 契约生成器 — MVP 使用手册
2
2
 
3
3
  ## 概述
4
4
 
5
- `glue-test` 是一个 TypeScript agent skill,用于从上游业务模块物料中提取结构化信息,归一化为 `crud-business-module/v1` 契约 JSON。该契约作为 AI Agent 生成 Playwright 测试脚本的地基,确保 Agent 不需要自己编造 selector、按钮文本或业务预期。
5
+ `glue-run-test` 是一个 TypeScript agent skill,用于从上游业务模块物料中提取结构化信息,归一化为 `crud-business-module/v1` 契约 JSON。该契约作为 AI Agent 生成 Playwright 测试脚本的地基,确保 Agent 不需要自己编造 selector、按钮文本或业务预期。
6
6
 
7
7
  当前 MVP 只面向公司自研 `zwplace` CRUD 场景,负责:
8
8
 
@@ -14,7 +14,7 @@
14
14
  ## 数据流
15
15
 
16
16
  ```
17
- 上游物料 glue-test 输出
17
+ 上游物料 glue-run-test 输出
18
18
  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
19
19
  │ HTML 页面 │──extractor──→ │ │ │ │
20
20
  │ spec.yaml │──extractor──→ │ normalizer │──CLI 输出──→ │ 契约 JSON │
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@epoint-testtech/ep-stage-skill",
3
- "version": "0.0.3-alpha.2",
3
+ "version": "0.0.4-alpha.1",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
7
+ "bin": {
8
+ "ep-stage-skill": "./dist/src/cli/index.js"
9
+ },
7
10
  "files": [
8
11
  "dist",
9
12
  "codex-skill",
@@ -31,8 +34,10 @@
31
34
  "typecheck": "tsc --noEmit",
32
35
  "test": "vitest run",
33
36
  "build": "tsc",
34
- "generate:crud-contract": "node --import tsx src/cli/generate-crud-contract.ts",
35
- "generate:playwright-tests": "node --import tsx src/cli/generate-playwright-tests.ts",
36
- "run:gap-pipeline": "node --import tsx src/cli/run-gap-pipeline.ts"
37
+ "generate:crud-contract": "node --import tsx src/cli/dev/extract-contract.ts",
38
+ "generate:playwright-tests": "node --import tsx src/cli/index.ts spec",
39
+ "run:gap-pipeline": "node --import tsx src/cli/run-gap-pipeline.ts",
40
+ "cli": "node --import tsx src/cli/index.ts",
41
+ "generate:testcase": "node --import tsx src/cli/index.ts testcase"
37
42
  }
38
43
  }
@@ -1,59 +0,0 @@
1
- ---
2
- name: create-project
3
- description: 使用时机:当用户需要通过现有 stage-create CLI 创建 ep-stage Playwright 项目(尤其是 default 或 glue 模式项目)时使用。
4
- ---
5
-
6
- # ep-stage: create-project
7
-
8
- 当用户需要创建 ep-stage 项目,或要求生成 glue 模式(glue-mode)Playwright 脚手架时,使用本 skill。
9
-
10
- ## 行为契约(Behavior Contract)
11
-
12
- 本 skill 引导 Agent 调用现有 `@epoint/stage-create` CLI,不重新实现脚手架逻辑。
13
-
14
- 当前命令示例:
15
-
16
- ```bash
17
- stage-create my-glue-project --mode glue
18
- stage-create my-default-project --mode default
19
- ```
20
-
21
- ## 必填输入
22
-
23
- - 项目名称(project name):必填,缺失时必须向用户询问。
24
- - 模式(mode):`glue` 或 `default`,缺失时必须向用户询问。
25
-
26
- 不要自行猜测项目名称。不要发明名为 `ep-stage: create-project` 的命令——那是 skill 名称,不是 shell 命令。
27
-
28
- ## 模式选择指引
29
-
30
- - 当项目需要包含胶水骨架(glue skeletons)、页面组件(page components)、报告辅助(report helpers)以及物料驱动的测试生成时,使用 `glue` 模式。
31
- - 当项目只需要标准 Playwright 基线时,使用 `default` 模式。
32
-
33
- ## 验证
34
-
35
- 创建项目后,验证输出目录存在且包含:
36
-
37
- ```text
38
- package.json
39
- playwright.config.ts
40
- tsconfig.json
41
- ```
42
-
43
- 对于 `glue` 模式,还需验证:
44
-
45
- ```text
46
- src/skeletons/
47
- src/web/component/
48
- src/report/
49
- ```
50
-
51
- ## glue 项目上下文
52
-
53
- 创建 glue 项目后必须生成(由 stage-create CLI 交互写入):
54
-
55
- - `<project>/stage-context.md`
56
- - `<project>/.env`
57
- - `~/.ep-stage/projects.index.json5`
58
-
59
- 这些文件供后续 `glue-testcase` 和 `glue-test` 内置读取,不依赖用户项目存在 `AGENTS.md`。
@@ -1,258 +0,0 @@
1
- ---
2
- name: glue-test
3
- description: 使用时机:当需要从上游需求文档、code_list.md、生成的 HTML 页面、Java Action 源码、ModuleHints 或 CrudFlowSlots 组装 ep-stage 项目的 Playwright CRUD 胶水测试(glue-code tests),或运行端到端 gap 推理工作流时使用。
4
- compatibility: 需要 Codex workspace 环境,配备 pnpm、Node.js、packages/ep-stage-skill,以及由 stage-create 生成的 glue 模式 Playwright 项目。
5
- metadata:
6
- source-package: "@epoint/ep-stage-skill"
7
- contract: "crud-business-module/v1"
8
- ---
9
-
10
- # ep-stage: glue-test
11
-
12
- ep-stage 项目中的胶水编码工作流使用本 skill。
13
-
14
- ## 概览(Overview)
15
-
16
- 本 skill 通过确定性提取器(deterministic extractors)、显式的 `ModuleHints` 策略文件、glue 模式 CRUD 骨架以及 gap runtime pipeline,将上游业务物料转换为可执行的 Playwright 胶水测试。
17
-
18
- 核心原则:Agent 负责组装并核实证据,不自行发明选择器(selector)、iframe 关键字、按钮文案、listbox 取值、数据唯一性规则或业务断言。
19
-
20
- **默认入口**:当用户要求端到端验证、运行时 gap 推理,或"静态组装 + 动态推理 + 落袋合并"时,优先使用一键 pipeline `run:gap-pipeline`。仅当用户明确希望在不执行真实页面的情况下生成 contract/spec 时,才回退到旧的两步离线流程。
21
-
22
- ## 当前后端(Current Backend)
23
-
24
- 当前运行时后端是 `@epoint/ep-stage-skill` 中现有的 CRUD + Export + gap pipeline。
25
-
26
- 本期只承载 skill 入口与工作流描述,不改变 `crud-business-module/v1`,不引入 `skeleton-registry`。当前已支持**默认入口所需字段**的轻量交互补齐:当 `run:gap-pipeline` 在 `material-inventory` 或 `menu` gate 发现 `code_list.md` 缺少 `knowledgeRoot`、`menu`、HTML、Java Action、`ModuleHints` 等关键入口信息时,TTY 环境下会提示用户补齐,并优先写回**可写的** `code_list.md`。当前仓内的真实业务验收主线是 `zwplace`,其唯一上游扎口是 `knowledge-project/epoint-web-v9.5.2/_docs/code_list.md`;仓内 `packages/ep-stage-skill/examples/zwplace.observable.code_list.md` 只是该只读物料的可写镜像。骨架项目或脚手架里顺带出现的说明信息不应替代 `code_list.md` 成为本源。非 CRUD 工作流泛化、`skeleton-registry`、交互式 `review-gaps` CLI 属于第二期源码级改造范围。
27
-
28
- 若后续要验证“不同系统的普通 CRUD 泛化”,应由用户补充第二个真实业务样本的 `code_list.md`;不要在当前链路中用脚手架说明信息、运行产物或旁证文档反推出第二个模块充当本源。
29
-
30
- **真实系统 E2E 运行约束:**
31
-
32
- - 禁止用 `--headless true` 跑真实业务系统 E2E。
33
- - 真实系统验证必须通过 `packages/ep-stage-skill/codex-skill/ep-stage` 这套 skill / `run:gap-pipeline` 入口,以 `--headless false` 运行。
34
- - 运行过程中必须有人在场观察页面行为、弹窗、登录状态和业务副作用;无人工观察的无头回放不算当前阶段验收证据。
35
- - `--headless true` 仅允许用于本地调试、结构验证或历史对比,不作为真实系统验收方式。
36
-
37
- ## 工作流(Workflow)
38
-
39
- 完整链路按步骤解耦如下:
40
-
41
- ```text
42
- explore-materials
43
- -> generate-contract
44
- -> match-skeleton
45
- -> review-gaps
46
- -> generate-spec
47
- -> infer-gaps
48
- -> run-tests
49
- -> generate-report
50
- ```
51
-
52
- 每个步骤既可端到端串联调用,也可单步独立调用(便于排查链路中某一步的问题、迭代局部产出、对中间产物有干预窗口)。
53
-
54
- ## 适用场景(Use This For)
55
-
56
- - 从需求文档、`code_list.md`、生成的 HTML 和 Java Action 文件生成 `crud-business-module/v1` 契约。
57
- - 生成调用 `LoginPage`、`MenuPage` 和 `CrudPage` 并使用 `CrudFlowSlots` 的 `.spec.ts` 文件。
58
- - 运行一键胶水 E2E 验证:静态组装 -> 运行时 gap 解决 -> 追加 `Custom` 测试 -> 执行 Playwright -> 产出 glue-report。
59
- - 当数据主键、搜索条件、listbox 取值、按钮别名、自动填充覆盖或删除策略属于策略决策时,更新 `ModuleHints`。
60
- - 模拟胶水编码链路:上游物料 -> 契约 -> 动态槽位 -> CRUD 骨架 -> Playwright 脚本 -> 编译/运行时验证。
61
- - 识别 CRUD + Export 骨架未覆盖的业务动作,并输出 `agentInferredWorkflows`。
62
- - 使用 `ModuleHints.customWorkflows` 约束自定义工作流的业务意图和断言预期。
63
-
64
- 不要将本 skill 用于绕过骨架的自由式 Playwright 编写,或用于 `stage-core` 核心运行时改动。
65
-
66
- ## 必须遵循的工作流(Required Workflow)
67
-
68
- ### 优先路径:一键 gap pipeline
69
-
70
- 1. 定位当前仓库根目录,确认 `packages/ep-stage-skill/package.json` 存在。
71
- 2. 运行前检查上游物料:
72
- - docs 目录,通常包含 `spec.yaml` 或模块文档
73
- - `code_list.md`
74
- - 生成的网页 HTML 目录
75
- - Java Action 源码目录
76
- - `ModuleHints` JSON
77
- 3. 运行 `run:gap-pipeline`。
78
- 4. 检查生成的摘要:
79
- - `contractPath`
80
- - `specPath`
81
- - `runTimestamp`
82
- - `stageGlueReportHtmlPath`
83
- - `playwrightReportDirPath`
84
- - `resolvedWorkflows` / `needsReviewWorkflows`
85
- 5. 若运行时 gap 解决失败,报告失败发生在:
86
- - 上游提取
87
- - 契约生成
88
- - spec 生成
89
- - 运行时解决
90
- - Playwright 执行
91
-
92
- ### 回退路径:离线两步生成
93
-
94
- 1. 定位当前仓库根目录,确认 `packages/ep-stage-skill/package.json` 存在。
95
- 2. 生成前检查上游物料:
96
- - docs 目录,通常包含 `spec.yaml` 或模块文档
97
- - `code_list.md`
98
- - 生成的网页 HTML 目录
99
- - Java Action 源码目录
100
- - `ModuleHints` JSON
101
- 3. 使用 `packages/ep-stage-skill` 生成契约。
102
- 4. 检查生成的契约:
103
- - `contractVersion` 为 `crud-business-module/v1`
104
- - `module.id` 和 `module.label` 与上游模块一致
105
- - `searchConditions` 包含预期的 CRUD 搜索条件
106
- - 在生成最终 spec 前 `unresolvedSlots` 为空
107
- 5. 将 Playwright spec 生成到 glue 模式项目中。
108
- 6. 验证生成的 spec 在消费方 glue 项目中能编译通过。
109
- 7. 仅当所需环境与业务系统可用时才运行 Playwright。
110
-
111
- 详细命令模式见 `references/crud-pipeline.md`。
112
-
113
- ## Gap 评审协议(Gap Review Protocol)
114
-
115
- 在运行时推理之前,尽可能向用户呈现 gap 清单:
116
-
117
- - `planned` 状态的 gap 可以进入运行时推理。
118
- - `candidate` 和 `unresolved` 状态的 gap 不得盲目追加到 spec。
119
- - 若某个 gap 缺少业务意图或断言预期,应询问用户是补充 `ModuleHints.customWorkflows`、本轮跳过,还是留待后续处理。
120
-
121
- 详细的第一期行为契约见 `references/gap-review-protocol.md`。
122
-
123
- ## 治理规则(Harness Rules)
124
-
125
- 在保证可靠性的前提下,使用最轻量的治理方式:
126
-
127
- | 治理关注点 | glue-test 规则 |
128
- | --- | --- |
129
- | 上下文交接(Context handoff) | 将契约 JSON 和生成的 spec 作为版本化产物保留。 |
130
- | 渐进式披露(Progressive disclosure) | 先加载本文件;仅按需打开 references。 |
131
- | 确定性(Determinism) | 优先使用提取器和 CLI 输出,而非 Agent 猜测。 |
132
- | 策略隔离(Strategy isolation) | 将人工/测试人员的决策放入 `ModuleHints`,而非提取器代码。 |
133
- | 评估(Evaluation) | 检查契约结构、编译输出,以及(可选)真实 Playwright 行为。 |
134
- | 反过拟合(Anti-overfit) | 将 `zwplace` 视为示例 fixture,而非唯一支持的模块。 |
135
-
136
- 治理原则的完整说明见 `references/harness-principles.md`。
137
-
138
- ## 快速命令格式(Quick Command Shape)
139
-
140
- ### 优先:一键 gap pipeline
141
-
142
- ```bash
143
- pnpm --filter @epoint/ep-stage-skill run:gap-pipeline -- \
144
- --module-id <module-id> \
145
- --docs <upstream-docs-dir> \
146
- --code-list <upstream-code-list-md> \
147
- --webapp <upstream-html-dir> \
148
- --java-actions <upstream-java-action-dir> \
149
- --hints <module-hints-json> \
150
- --menu "<menu-path>" \
151
- --project-dir <glue-project-dir> \
152
- --headless false
153
- ```
154
-
155
- 当用户要求以下场景时使用:
156
-
157
- - 真实端到端验证
158
- - 运行时 gap 推理
159
- - 真实页面补证据
160
- - 自动把 `Custom` test 追加到现有 suite
161
-
162
- ### 回退:仅离线生成
163
-
164
- ```bash
165
- pnpm --filter @epoint/ep-stage-skill generate:crud-contract -- \
166
- --module-id <module-id> \
167
- --docs <upstream-docs-dir> \
168
- --code-list <upstream-code-list-md> \
169
- --webapp <upstream-html-dir> \
170
- --java-actions <upstream-java-action-dir> \
171
- --hints <module-hints-json> \
172
- --out output/<module-id>.crud.contract.json
173
-
174
- pnpm --filter @epoint/ep-stage-skill generate:playwright-tests -- \
175
- --contract output/<module-id>.crud.contract.json \
176
- --out <glue-project>/src/tests/<name>.spec.ts \
177
- --menu "<menu-path>"
178
- ```
179
-
180
- 通过 `pnpm --filter` 传路径时,上游文件和输出 spec 建议使用绝对路径。相对路径从 `packages/ep-stage-skill` 解析。
181
-
182
- 真实系统 E2E 请固定使用:
183
-
184
- ```bash
185
- pnpm --filter @epoint/ep-stage-skill run:gap-pipeline -- \
186
- --code-list <code_list.md> \
187
- --project-dir <glue-project-dir> \
188
- --scenario <confirmed-scenario> \
189
- --headless false
190
- ```
191
-
192
- ## 常见错误(Common Mistakes)
193
-
194
- - 用户明确要 E2E 验证时,仍然只跑 `generate:crud-contract` + `generate:playwright-tests`,没有进入 `run:gap-pipeline`。
195
- - 在 `unresolvedSlots` 非空时使用生成的 `.spec.ts`。
196
- - 从截图猜测 listbox 取值,而不是将冒烟测试值放入 `ModuleHints.searchConditions`。
197
- - 把 `dataKey` 和 `searchConditions` 当作互相竞争的独立策略。当前 glue CRUD 流程由 `searchConditions` 驱动。
198
- - 在生成的 spec 中内联 `page.fill()` 或 `page.click()` 流程,而不是调用骨架。
199
- - 当真实系统、登录环境或内网不可用时,仍假设业务 Playwright 运行失败是代码问题。
200
- - 只凭按钮文本生成 Custom test。
201
- - 把 `candidate` 或 `unresolved` 的 gap workflow 直接追加到 spec。
202
- - 在 runtime gap resolve 阶段修改 `businessIntent` 或 `assertionExpectation`。
203
- - 在 gap 代码中修改 `src/skeletons/*.ts`。
204
-
205
- ## 边界(Boundaries)
206
-
207
- 不要声称本期已实现非 CRUD 工作流的生成。若用户要求审批流、流程发起或表单提交等超出当前后端能力的工作流,应说明这些属于第二期源码级泛化范围。
208
-
209
- 处理运行时 gap 推理时,不要修改 `src/skeletons/*.ts`。
210
-
211
- ## 参考文档(References)
212
-
213
- - `references/crud-pipeline.md`:通用 CRUD 组装 pipeline 与验证命令。
214
- - `references/harness-principles.md`:本 skill 如何在不发生过拟合(不绑定单一模块或模型)的前提下应用 harness 工程。
215
- - `references/gap-review-protocol.md`:`review-gaps` 步骤的第一期 Agent 行为协议。
216
- - `scripts/generate-crud-spec.mjs --help`:两个包 CLI 的确定性封装。
217
-
218
- ## 可观测默认入口
219
-
220
- 默认只要求用户提供 `code_list.md`(`run:gap-pipeline -- --code-list <path>`)。`code_list.md` 是上游物料统一输入扎口:端到端链路需要的 `knowledgeRoot`、`menu` / `menuPath`、HTML、Java Action、spec、ModuleHints 等上游路径信息应优先写入该文件。当前 repo 的真实验收口径下,应优先把 `knowledge-project/epoint-web-v9.5.2/_docs/code_list.md` 视为真相源;若因主仓只读无法直接回写,再退到它的可写镜像 `packages/ep-stage-skill/examples/zwplace.observable.code_list.md`。若缺失入口字段:
221
-
222
- - `material-inventory` gate 会在 TTY 环境下提示补齐 `knowledgeRoot` / `moduleId` / `webappDir` / `javaActionsDir` / `hintsPath` / `menu`。
223
- - `menu` gate 会在 TTY 环境下再次提示确认菜单路径。
224
- - 若目标 `code_list.md` 位于**主仓只读** `knowledge-project/...`,补齐结果只对本次运行生效,不会写回受保护物料;若目标是外置可写 `code_list.md`,则会按当前格式回写。
225
-
226
- 调试时可继续传 `--docs`、`--webapp`、`--java-actions`、`--hints`、`--project-dir`、`--menu` 做覆盖;覆盖参数只用于开发观测,不作为默认业务输入方式。场景推理后用 `--scenario <候选>` 人工确认继续。
227
-
228
- 若目标是**真实系统验收**,除场景确认外还必须满足:
229
-
230
- - 以 `--headless false` 有头模式运行;
231
- - 运行时有人观察页面实际行为;
232
- - 将观察结论与 `.stage/trace/<run-id>/summary.md`、`playwright-execution.json`、`glue-report` 交叉核对后,才可作为验收证据。
233
-
234
- 当前一期对“普通 CRUD,不考虑嵌套 CRUD”的处理口径是:
235
-
236
- - 若人工确认场景为 `crud.single-page`,`nestedCrudCandidates` 仍保留在 coverage / reasoning 证据中;
237
- - 但它们不再阻断 testcase gate,不需要再额外 `--confirm-testcases` 才能继续普通 CRUD 主链路;
238
- - 真正的业务失败应由后续 runtime / playwright / glue-report 给出结构化结论。
239
-
240
- 链路顺序(每阶段写 `.stage/trace/<run-id>/*.json` + `summary.md`):
241
-
242
- ```text
243
- code_list.md
244
- -> context-resolution
245
- -> material-inventory (gate)
246
- -> evidence-extraction
247
- -> capability-candidates
248
- -> scenario-inference (gate, --scenario 确认)
249
- -> skeleton-capability-model
250
- -> coverage-diff
251
- -> glue-testcase (gate)
252
- -> glue spec assembly (unresolvedSlots gate)
253
- -> runtime gap inference
254
- -> Playwright execution
255
- -> glue-report
256
- ```
257
-
258
- 任一 gate `needs_review` 时停止(退出码 2),不继续后续阶段。用例中间产物由 `glue-testcase` skill 负责审阅。