@xulthekl/team-flow 0.33.0 → 0.34.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 (34) hide show
  1. package/.claude/always/phase-guard.md +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/.cursor-plugin/marketplace.json +1 -1
  6. package/.cursor-plugin/plugin.json +1 -1
  7. package/.github/plugin/marketplace.json +2 -2
  8. package/AGENTS.md +2 -0
  9. package/CHANGELOG.md +35 -0
  10. package/CONTRIBUTING.md +44 -0
  11. package/GEMINI.md +1 -1
  12. package/INSTALL.md +1 -1
  13. package/README.md +1 -1
  14. package/docs/README_en.md +1 -1
  15. package/docs/solutions/INDEX.md +1 -0
  16. package/docs/solutions/cross-phase/2026-08-04-no-summary.md +17 -0
  17. package/gemini-extension.json +1 -1
  18. package/hooks/session-start +2 -2
  19. package/llms.txt +1 -1
  20. package/package.json +1 -1
  21. package/plugin.json +1 -1
  22. package/scripts/lib/conventions-generator.mjs +350 -0
  23. package/scripts/lib/test-record.mjs +65 -2
  24. package/skills/test-strategy/SKILL.md +37 -0
  25. package/skills/test-strategy/references/integration-test-contracts.md +237 -0
  26. package/skills/test-strategy/references/integration-test-isolation.md +346 -0
  27. package/skills/test-strategy/references/test-quality-rules.md +292 -0
  28. package/skills/workflow-bootstrap/SKILL.md +40 -3
  29. package/templates/agent-template.md +41 -0
  30. package/templates/conventions/_manifest.json +39 -0
  31. package/templates/conventions/glaf4-compliant/java-testing.md +367 -0
  32. package/templates/conventions/glaf4-compliant/spring-patterns.md +415 -0
  33. package/templates/conventions/js-testing.md +261 -0
  34. package/templates/conventions/python-testing.md +333 -0
@@ -93,6 +93,55 @@ const PARSERS = {
93
93
  pytest: parsePytest,
94
94
  };
95
95
 
96
+ // ── Failure Analysis 分类法(v0.13 §57,来自 glaf4-test analyze-surefire-failures.py)────────
97
+
98
+ /** 测试失败分类:assertion_failure / runtime_error / framework_error / compile_error / dependency_blocker / unknown */
99
+ export function classifyFailure(text) {
100
+ const lower = text.toLowerCase();
101
+
102
+ // 1. 编译错误
103
+ if (lower.includes('compilation error') || lower.includes('cannot find symbol') ||
104
+ lower.includes('incompatible types') || lower.includes('method does not override') ||
105
+ lower.includes('syntaxerror') || lower.includes('indentationerror')) {
106
+ return 'compile_error';
107
+ }
108
+
109
+ // 2. 依赖阻塞
110
+ if (lower.includes('connection refused') || lower.includes('connection timed out') ||
111
+ lower.includes('unknownhostexception') || lower.includes('could not resolve host') ||
112
+ lower.includes('no such file or directory') || lower.includes('module not found') ||
113
+ lower.includes('package does not exist') || lower.includes('dependency') && lower.includes('failed')) {
114
+ return 'dependency_blocker';
115
+ }
116
+
117
+ // 3. 框架错误
118
+ if (lower.includes('applicationcontextexception') || lower.includes('beandefinitionstoreexception') ||
119
+ lower.includes('nosuchbeandefinitionexception') || lower.includes('unsatisfieddependencyexception') ||
120
+ lower.includes('spring') && lower.includes('failed to load') ||
121
+ lower.includes('contextconfiguration') || lower.includes('testcontext')) {
122
+ return 'framework_error';
123
+ }
124
+
125
+ // 4. 运行时异常
126
+ if (lower.includes('nullpointerexception') || lower.includes('illegalargumentexception') ||
127
+ lower.includes('indexoutofboundsexception') || lower.includes('classcastexception') ||
128
+ lower.includes('numberformatexception') || lower.includes('stackoverflowerror') ||
129
+ lower.includes('outofmemoryerror') || lower.includes('runtimeerror') ||
130
+ lower.includes('typeerror') || lower.includes('referenceerror')) {
131
+ return 'runtime_error';
132
+ }
133
+
134
+ // 5. 断言失败
135
+ if (lower.includes('assertionerror') || lower.includes('expected') && lower.includes('but was') ||
136
+ lower.includes('assertionfailederror') || lower.includes('expected :') && lower.includes('actual :') ||
137
+ lower.includes('expect(') || lower.includes('assert') && lower.includes('failed')) {
138
+ return 'assertion_failure';
139
+ }
140
+
141
+ // 6. 未知
142
+ return 'unknown';
143
+ }
144
+
96
145
  /** auto 识别:按内容特征匹配 runner。 */
97
146
  export function detectRunner(text) {
98
147
  const trimmed = text.trim();
@@ -180,7 +229,18 @@ export async function run(args) {
180
229
  // 判定:failed==0 且 total>0 才算 pass(total=0 空真拒绝,v0.13 §50.2)
181
230
  const verdict = stats.failed === 0 && stats.total > 0 ? 'pass' : 'fail';
182
231
  const ts = new Date().toISOString();
183
- const record = `${verdict}: total=${stats.total} passed=${stats.passed} failed=${stats.failed} skipped=${stats.skipped} runner=${runner} recorded-by=tf-test-record ts=${ts}`;
232
+
233
+ // Failure Analysis 分类(v0.13 §57,来自 glaf4-test)
234
+ let failureClass = null;
235
+ if (verdict === 'fail') {
236
+ const rawText = fromStat.isFile()
237
+ ? readFileSync(fromPath, 'utf-8')
238
+ : '';
239
+ failureClass = classifyFailure(rawText);
240
+ }
241
+
242
+ const failureInfo = failureClass ? ` failure_class=${failureClass}` : '';
243
+ const record = `${verdict}: total=${stats.total} passed=${stats.passed} failed=${stats.failed} skipped=${stats.skipped} runner=${runner} recorded-by=tf-test-record ts=${ts}${failureInfo}`;
184
244
 
185
245
  // 原始证据落盘(tests-passing 门禁与 doctor 巡检都要求该文件存在)
186
246
  const evidenceDir = join(changeDir, '.superpowers', 'test-evidence');
@@ -200,11 +260,14 @@ export async function run(args) {
200
260
  writeState(changeDir, state);
201
261
 
202
262
  if (values.json) {
203
- console.log(JSON.stringify({ ok: true, verdict, ...stats, runner, test_result: record, test_evidence_path: evidenceRel }));
263
+ const jsonResult = { ok: true, verdict, ...stats, runner, test_result: record, test_evidence_path: evidenceRel };
264
+ if (failureClass) jsonResult.failure_class = failureClass;
265
+ console.log(JSON.stringify(jsonResult));
204
266
  } else {
205
267
  console.log(`${verdict === 'pass' ? '✅' : '❌'} test_result recorded (${runner}): total=${stats.total} passed=${stats.passed} failed=${stats.failed} skipped=${stats.skipped}`);
206
268
  console.log(` evidence: ${evidenceRel}`);
207
269
  if (verdict === 'fail') {
270
+ console.log(` failure_class: ${failureClass}`);
208
271
  console.log(' closing 将被 tests-passing 门禁阻断:修复失败后重新运行测试套件并再次 tf test record。');
209
272
  }
210
273
  }
@@ -68,3 +68,40 @@ user-invocable: false
68
68
  | **TDD** | 新功能/新行为 | RED→GREEN→REFACTOR |
69
69
  | **CHARACTERIZATION** | 遗留代码行为捕获 | 只写不改(不改生产代码) |
70
70
  | **REGRESSION** | 缺陷复现+修复 | 先复现再修 |
71
+
72
+ ## 8. 组合覆盖声明
73
+
74
+ > 来源:glaf4-test design-worker 的 combination_coverage 机制(v0.13 §55)
75
+
76
+ 当目标方法满足以下条件之一时,矩阵中**必须声明**组合覆盖策略:
77
+
78
+ ### 触发条件
79
+
80
+ 1. **多参数方法**(param_count > 1):声明 `pairwise`,要求至少一个 equivalence/boundary 用例覆盖参数组合
81
+ 2. **有分支逻辑**(if/case/switch):声明 `branch`,要求至少一个 state/path 用例覆盖各分支
82
+
83
+ ### 声明格式
84
+
85
+ 在 test-matrix.md 的 description 列中声明:
86
+
87
+ - `[pairwise] 已覆盖参数组合 A×B, A×C`
88
+ - `[branch] 已覆盖 true/false 分支`
89
+ - `[not_applicable] 单参数无分支,无需组合覆盖`
90
+
91
+ ### 对账规则
92
+
93
+ contract-builder 生成矩阵后,必须校验:
94
+ - 声明 `pairwise` 的目标,必须有至少 1 个 equivalence 或 boundary 用例覆盖参数组合
95
+ - 声明 `branch` 的目标,必须有至少 1 个 state 或 path 用例覆盖各分支
96
+ - 声明 `not_applicable` 的目标,必须提供理由(如"单参数无分支")
97
+
98
+ ### 示例
99
+
100
+ ```markdown
101
+ | ID | work_mode | test_tier | design_method | description | priority |
102
+ |----|-----------|-----------|---------------|-------------|----------|
103
+ | TC-001 | TDD | unit | equivalence | [pairwise] 正常查询:page=1, size=10 | P0 |
104
+ | TC-002 | TDD | unit | boundary | [pairwise] 边界:page=0, size=10 | P1 |
105
+ | TC-003 | TDD | unit | boundary | [pairwise] 边界:page=1, size=0 | P1 |
106
+ | TC-004 | TDD | unit | error | [not_applicable] 单参数无分支,无需组合覆盖 | P1 |
107
+ ```
@@ -0,0 +1,237 @@
1
+ # Integration Test Contracts(集成测试契约)
2
+
3
+ > 来源:glaf4-test social-test-contracts.md 的通用模式(v0.13 §58)
4
+ > 用途:集成测试的组织方法论,contract-builder 生成矩阵时参考
5
+
6
+ ---
7
+
8
+ ## 一、核心概念
9
+
10
+ **社交测试(Social Test)**:跨类/跨层交互的测试,需要声明式契约来明确测试边界和依赖。
11
+
12
+ **契约的作用**:
13
+ - 明确测试的输入和输出
14
+ - 声明依赖的真实/mock/stub
15
+ - 定义测试隔离和清理策略
16
+ - 确保测试可重复和可维护
17
+
18
+ ---
19
+
20
+ ## 二、五种契约类型
21
+
22
+ ### 1. 入口契约(Entry Contract)
23
+
24
+ **定义**:系统边界入口声明
25
+
26
+ **内容**:
27
+ - API 端点(URL、HTTP 方法、请求格式)
28
+ - 消息队列(exchange、routingKey、消息格式)
29
+ - 定时任务(cron 表达式、触发条件)
30
+
31
+ **示例**:
32
+ ```markdown
33
+ ## 入口契约
34
+
35
+ - API: `POST /api/users`
36
+ - Content-Type: application/json
37
+ - 请求体: `{ "name": "string", "email": "string" }`
38
+ - 认证: Bearer Token
39
+ ```
40
+
41
+ ### 2. 协作者契约(Collaborator Contract)
42
+
43
+ **定义**:依赖分级声明
44
+
45
+ **分级**:
46
+ | 级别 | 说明 | 使用场景 |
47
+ |------|------|---------|
48
+ | **真实(Real)** | 使用真实实现 | Repository 层、内部 Service |
49
+ | **Mock** | 使用 mock 框架创建 | 外部 API、第三方服务 |
50
+ | **Stub** | 使用固定返回值 | 简单依赖、配置服务 |
51
+
52
+ **示例**:
53
+ ```markdown
54
+ ## 协作者契约
55
+
56
+ | 协作者 | 级别 | 理由 |
57
+ |--------|------|------|
58
+ | UserRepository | Real | 测试真实持久化逻辑 |
59
+ | EmailService | Mock | 外部服务,避免真实发送 |
60
+ | ConfigService | Stub | 返回固定配置值 |
61
+ ```
62
+
63
+ ### 3. 数据契约(Data Contract)
64
+
65
+ **定义**:测试数据规格声明
66
+
67
+ **内容**:
68
+ - 输入数据格式和约束
69
+ - 输出数据格式和验证点
70
+ - 测试数据准备方式
71
+
72
+ **示例**:
73
+ ```markdown
74
+ ## 数据契约
75
+
76
+ ### 输入
77
+ - name: string, 1-50 字符
78
+ - email: string, 有效邮箱格式
79
+
80
+ ### 输出
81
+ - User 对象,包含 id、name、email、createdAt
82
+ - id: 雪花算法生成,非空
83
+ - createdAt: 当前时间,非空
84
+
85
+ ### 准备方式
86
+ - 使用 Builder 模式构建测试数据
87
+ - 每个测试独立数据,避免共享状态
88
+ ```
89
+
90
+ ### 4. 中间件契约(Middleware Contract)
91
+
92
+ **定义**:基础设施交互规格
93
+
94
+ **内容**:
95
+ | 中间件 | 交互方式 | 测试策略 |
96
+ |--------|---------|---------|
97
+ | **数据库** | SQL 查询/写入 | H2 内存库 / @Transactional 回滚 |
98
+ | **消息队列** | 发送/接收消息 | rabbitmq-mock / embedded broker |
99
+ | **缓存** | 读写 Redis | embedded-redis / mock |
100
+ | **外部 HTTP** | 调用第三方 API | MockWebServer / WireMock |
101
+
102
+ **示例**:
103
+ ```markdown
104
+ ## 中间件契约
105
+
106
+ | 中间件 | 交互 | 测试策略 |
107
+ |--------|------|---------|
108
+ | MySQL | INSERT/SELECT | H2 内存库,@Transactional 回滚 |
109
+ | RabbitMQ | 发送用户创建事件 | rabbitmq-mock |
110
+ | Redis | 缓存用户信息 | embedded-redis (port 6378) |
111
+ | 支付网关 | 调用支付 API | MockWebServer |
112
+ ```
113
+
114
+ ### 5. 清理契约(Cleanup Contract)
115
+
116
+ **定义**:测试隔离清理声明
117
+
118
+ **原则**:
119
+ - 每个测试独立,不共享状态
120
+ - 测试后清理所有创建的数据
121
+ - 异步操作需要等待完成
122
+
123
+ **策略**:
124
+ | 场景 | 清理方式 |
125
+ |------|---------|
126
+ | **同步操作** | @Transactional 自动回滚 |
127
+ | **异步操作** | 手动清理(@AfterEach) |
128
+ | **消息队列** | 清空队列 |
129
+ | **缓存** | 清空 key |
130
+
131
+ **示例**:
132
+ ```markdown
133
+ ## 清理契约
134
+
135
+ - 数据库:@Transactional 自动回滚
136
+ - 消息队列:@AfterEach 清空队列
137
+ - 缓存:@AfterEach 清空测试 key
138
+ - ThreadLocal:@AfterEach 清理 TraceIdHolder
139
+ ```
140
+
141
+ ---
142
+
143
+ ## 三、契约声明格式
144
+
145
+ 在 test-matrix.md 的集成测试 case 中,使用以下格式声明契约:
146
+
147
+ ```markdown
148
+ | ID | work_mode | test_tier | design_method | description | priority | mock |
149
+ |----|-----------|-----------|---------------|-------------|----------|------|
150
+ | TC-010 | TDD | integration | equivalence | [contract] 创建用户:POST /api/users | P0 | entry:POST /api/users, collaborator:EmailService=Mock, data:User{name,email}, cleanup:@Transactional |
151
+ ```
152
+
153
+ **字段说明**:
154
+ - `entry`: 入口契约
155
+ - `collaborator`: 协作者契约(Real/Mock/Stub)
156
+ - `data`: 数据契约
157
+ - `middleware`: 中间件契约
158
+ - `cleanup`: 清理契约
159
+
160
+ ---
161
+
162
+ ## 四、矩阵生成指南
163
+
164
+ ### contract-builder 生成集成测试矩阵时:
165
+
166
+ 1. **识别入口**:从 specs/*.md 中提取 API 端点、消息队列、定时任务
167
+ 2. **分析依赖**:从代码中识别所有依赖,按真实/mock/stub 分级
168
+ 3. **定义数据**:明确输入输出数据格式
169
+ 4. **选择中间件**:识别涉及的基础设施,选择测试策略
170
+ 5. **设计清理**:根据操作类型(同步/异步)设计清理策略
171
+
172
+ ### 示例:用户注册功能
173
+
174
+ ```markdown
175
+ ## 集成测试矩阵
176
+
177
+ ### TC-010: 创建用户成功
178
+ - 入口:POST /api/users
179
+ - 协作者:UserRepository=Real, EmailService=Mock
180
+ - 数据:{name:"John", email:"john@example.com"}
181
+ - 中间件:MySQL=H2
182
+ - 清理:@Transactional
183
+
184
+ ### TC-011: 创建用户失败(邮箱已存在)
185
+ - 入口:POST /api/users
186
+ - 协作者:UserRepository=Real(预先插入重复数据)
187
+ - 数据:{name:"John", email:"existing@example.com"}
188
+ - 中间件:MySQL=H2
189
+ - 清理:@Transactional
190
+ - 预期:409 Conflict
191
+
192
+ ### TC-012: 创建用户后发送欢迎邮件
193
+ - 入口:POST /api/users
194
+ - 协作者:UserRepository=Real, EmailService=Mock
195
+ - 数据:{name:"John", email:"john@example.com"}
196
+ - 中间件:MySQL=H2, RabbitMQ=rabbitmq-mock
197
+ - 清理:@Transactional + 清空队列
198
+ - 验证:EmailService.sendWelcomeEmail() 被调用
199
+ ```
200
+
201
+ ---
202
+
203
+ ## 五、最佳实践
204
+
205
+ ### 1. 契约最小化
206
+ - 只声明必要的契约
207
+ - 避免过度 mock(内部依赖尽量用真实实现)
208
+
209
+ ### 2. 契约可读性
210
+ - 使用表格格式,清晰易读
211
+ - 提供理由说明(为什么选择 Mock/Stub)
212
+
213
+ ### 3. 契约可维护性
214
+ - 契约与测试代码同步更新
215
+ - 定期审查契约的有效性
216
+
217
+ ### 4. 契约复用
218
+ - 相似功能的契约可以复用
219
+ - 提取公共契约模板
220
+
221
+ ---
222
+
223
+ ## 六、与 test-strategy 的关系
224
+
225
+ 集成测试契约是 test-strategy §1(Design Method 选择规则)的补充:
226
+ - **基础级**(equivalence/boundary/error):适用于所有测试
227
+ - **扩展级**(path/state/exception/reject):条件触发
228
+ - **高级**(permission/idempotency/concurrency/contract):场景触发
229
+ - **contract**:跨模块/跨服务接口契约,需要声明集成测试契约
230
+
231
+ ---
232
+
233
+ ## 变更记录
234
+
235
+ | 日期 | 版本 | 变更内容 |
236
+ |------|------|---------|
237
+ | 2026-08-04 | v1.0 | 从 glaf4-test social-test-contracts.md 抽取通用模式 |