@xulthekl/team-flow 0.29.2 → 0.31.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.
- package/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +2 -2
- package/.github/plugin/marketplace.json +2 -2
- package/AGENTS.md +10 -4
- package/CHANGELOG.md +88 -0
- package/GEMINI.md +1 -1
- package/HANDOFF.md +4 -4
- package/INSTALL.md +1 -1
- package/README.md +5 -5
- package/agents/architecture-design.md +1 -0
- package/agents/build-executor.md +81 -0
- package/agents/contract-builder.md +78 -0
- package/agents/cross-change-consistency-checker.md +1 -1
- package/agents/need-explorer.md +67 -0
- package/agents/release-archivist.md +82 -0
- package/agents/spec-writer.md +83 -0
- package/docs/README_en.md +1 -1
- package/gemini-extension.json +1 -1
- package/hooks/session-start +2 -2
- package/llms.txt +1 -1
- package/package.json +2 -2
- package/plugin.json +2 -2
- package/scripts/ensure-branch.mjs +200 -42
- package/scripts/guard/checks/test-matrix-complete.mjs +67 -0
- package/scripts/guard/guard.mjs +5 -1
- package/scripts/lib/cmd-doctor.mjs +40 -1
- package/scripts/lib/cmd-state.mjs +33 -13
- package/scripts/lib/hash.mjs +11 -0
- package/scripts/lib/state-loader.mjs +34 -1
- package/scripts/lib/test-matrix-export.mjs +231 -0
- package/scripts/lib/test-merge.mjs +540 -0
- package/scripts/team-flow.mjs +6 -0
- package/skills/build-executor/SKILL.md +14 -4
- package/skills/build-executor/implementer-prompt.md +38 -3
- package/skills/code-reviewer/SKILL.md +28 -1
- package/skills/code-reviewer/code-reviewer-prompt.md +10 -0
- package/skills/contract-builder/SKILL.md +78 -0
- package/skills/need-explorer/SKILL.md +2 -0
- package/skills/release-archivist/SKILL.md +37 -2
- package/skills/spec-writer/SKILL.md +5 -1
- package/skills/test-strategy/SKILL.md +70 -0
- package/skills/test-strategy/references/adversarial-patterns.md +0 -0
- package/skills/test-strategy/references/complexity-grading.md +137 -0
- package/skills/test-strategy/references/design-methods-detail.md +183 -0
- package/skills/workflow-orchestrator/references/s1-path-router.md +4 -0
- package/skills/workflow-start/SKILL.md +29 -15
- package/skills/workflow-start/references/routing-rules.md +29 -6
- package/tests/lib/cmd-install-workbuddy.test.mjs +1 -1
- package/tests/lib/ensure-branch.test.mjs +52 -1
|
@@ -134,6 +134,31 @@ Check for:
|
|
|
134
134
|
- **Edge cases**: Tests cover boundary conditions, error cases
|
|
135
135
|
- **Test quality**: Tests are meaningful (not just "it works"), assertions are specific
|
|
136
136
|
|
|
137
|
+
### Step 5b: Test Matrix Compliance (v0.12 §44.3)
|
|
138
|
+
|
|
139
|
+
If `test-matrix.md` exists in the change directory, audit the implementation against it:
|
|
140
|
+
|
|
141
|
+
1. **Case-by-case verification**: For each case in the matrix:
|
|
142
|
+
- Check if the test implementation exists (`test_file` + `test_method_name` match)
|
|
143
|
+
- Verify assertions match the matrix's `expected` output
|
|
144
|
+
- Verify `design_method` matches actual test approach (a `boundary` case must use real boundary values, not a happy-path disguised as boundary)
|
|
145
|
+
|
|
146
|
+
2. **Coverage calculation**:
|
|
147
|
+
- Matrix coverage = implemented cases / total cases in matrix
|
|
148
|
+
- Matrix coverage < 100% → **Critical finding** (test-matrix-gap)
|
|
149
|
+
- List missing case_ids
|
|
150
|
+
|
|
151
|
+
3. **Candidate Coverage Ledger audit**:
|
|
152
|
+
- Entries with `decision=deferred` have a reasonable `reason`?
|
|
153
|
+
- Entries with `decision=covered` actually have corresponding tests?
|
|
154
|
+
|
|
155
|
+
4. **Pyramid ratio check**:
|
|
156
|
+
- unit cases: 70-80% of total
|
|
157
|
+
- integration cases: ≤30% of total
|
|
158
|
+
- Significant deviation → **Important finding** (test-pyramid-imbalance)
|
|
159
|
+
|
|
160
|
+
If `test-matrix.md` does NOT exist, skip this step silently (legacy change compatibility).
|
|
161
|
+
|
|
137
162
|
### Step 6: Documentation Review
|
|
138
163
|
|
|
139
164
|
Check for:
|
|
@@ -156,7 +181,9 @@ Check for:
|
|
|
156
181
|
|---------|-----------|
|
|
157
182
|
| **PASS** | No Critical or Important findings |
|
|
158
183
|
| **PASS_WITH_WARNINGS** | No Critical, but Important findings exist |
|
|
159
|
-
| **FAIL** | Any Critical finding |
|
|
184
|
+
| **FAIL** | Any Critical finding (including Test Matrix Compliance gaps — v0.12 §44.3) |
|
|
185
|
+
|
|
186
|
+
Test Matrix Compliance Critical findings carry the same weight as Spec Compliance violations — matrix gaps are always Critical, never Important.
|
|
160
187
|
|
|
161
188
|
## Calibration Rules
|
|
162
189
|
|
|
@@ -68,6 +68,16 @@ Subagent (general-purpose):
|
|
|
68
68
|
- Integration tests where they matter?
|
|
69
69
|
- All tests passing?
|
|
70
70
|
|
|
71
|
+
**Test Matrix Compliance (v0.12 §44.3):**
|
|
72
|
+
If `test-matrix.md` exists, audit against it:
|
|
73
|
+
- Each case has a corresponding test implementation (test_file + test_method_name match)?
|
|
74
|
+
- Assertions match the matrix's `expected` output?
|
|
75
|
+
- `design_method` matches actual test approach (boundary case uses real boundary values)?
|
|
76
|
+
- Matrix coverage < 100% → Critical finding (test-matrix-gap)
|
|
77
|
+
- Candidate Coverage Ledger: deferred items have reasonable reasons?
|
|
78
|
+
- Pyramid ratio: unit 70-80%, integration ≤30%?
|
|
79
|
+
If `test-matrix.md` does NOT exist, skip this section silently.
|
|
80
|
+
|
|
71
81
|
**Production readiness:**
|
|
72
82
|
- Migration strategy if schema changed?
|
|
73
83
|
- Backward compatibility considered?
|
|
@@ -11,6 +11,13 @@ Read before generating: `proposal.md`, `specs/`, `design.md`, `tasks.md`, then l
|
|
|
11
11
|
|
|
12
12
|
**Architecture Design Outputs (v0.9 §26)**: 若 `architecture/` 目录存在,同时读取 `architecture/architecture.md` / `database.md` / `api.md`,作为执行契约的架构约束补充输入——确保 execution-contract.md 的 Implementation Constraints 段包含架构设计的关键约束(聚合边界/CQRS 分流/API 契约/schema 变更)。`architecture/` 不存在时跳过。
|
|
13
13
|
|
|
14
|
+
**Test Ledger Injection (v0.12 §43.5)**: 若 `docs/test-ledger/` 存在,读取:
|
|
15
|
+
1. `docs/test-ledger/INDEX.md` → 获取相关模块的测试覆盖概览(coverage_status)
|
|
16
|
+
2. `docs/test-ledger/baselines/{module}.md` → 获取已有 case,避免重复设计;读取 Deferred Items → 评估本次是否可解决
|
|
17
|
+
3. 将已有 baseline 和 deferred 项作为 test-matrix.md 生成的增量输入
|
|
18
|
+
|
|
19
|
+
`docs/test-ledger/` 不存在时跳过(首次使用或无历史数据)。
|
|
20
|
+
|
|
14
21
|
## Artifact Mapping
|
|
15
22
|
|
|
16
23
|
| Source | Extract |
|
|
@@ -34,6 +41,75 @@ Before finalizing:
|
|
|
34
41
|
|
|
35
42
|
Must make obvious: approved behavior, out-of-scope, constraints, batches, test obligations, review gates, and conditions that force a rewind to planning. Prefer compression over repeating planning details.
|
|
36
43
|
|
|
44
|
+
## Test Matrix Generation (v0.12 §42)
|
|
45
|
+
|
|
46
|
+
`test-matrix.md` 是 `execution-contract.md` 的**附属产物**(不是独立第 6 核心产物),在 contract 的 `## Test Matrix` 段引用。
|
|
47
|
+
|
|
48
|
+
### Generation Protocol
|
|
49
|
+
|
|
50
|
+
1. **输入来源**:specs/(Scenario + Unit/Integration 标签)、tasks.md(batch + file structure)、test-strategy skill(design_method 规则)、test-ledger baselines(增量输入)
|
|
51
|
+
2. **按模块分组**:为每个有业务逻辑的模块(Service/Controller/Repository 等)生成 case 列表
|
|
52
|
+
3. **复杂度分级**:每个模块标注 trivial/medium/complex,作为用例数下限判据(test-strategy §2)
|
|
53
|
+
4. **design_method 覆盖**:每个模块至少 1 个 `{boundary, equivalence}` case + 1 个 `{error, exception, reject}` case(test-strategy §6 schema 强制覆盖)
|
|
54
|
+
5. **对抗验证**:矩阵生成后执行三招回检(test-strategy §4),缺失则追加 adversarial case
|
|
55
|
+
6. **候选覆盖台账**:列出所有被测候选(方法/类),标注 decision(covered/deferred/not_applicable)
|
|
56
|
+
|
|
57
|
+
### 12-Column Format
|
|
58
|
+
|
|
59
|
+
| case_id | behavior | design_method | input | expected | test_kind | test_tier | mock | work_mode | test_file | test_method_name | run_command |
|
|
60
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
61
|
+
|
|
62
|
+
字段说明见 test-strategy skill 的 `references/design-methods-detail.md`。`test_tier` 从 `test_kind` 派生(unit/integration)。
|
|
63
|
+
|
|
64
|
+
### Structure
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
# Test Matrix — {change-name}
|
|
68
|
+
|
|
69
|
+
## Summary
|
|
70
|
+
- Total cases: {N}
|
|
71
|
+
- Modules covered: {N} (complexity: trivial×{n}, medium×{n}, complex×{n})
|
|
72
|
+
- Unit cases: {N} ({percent}%)
|
|
73
|
+
- Integration cases: {N} ({percent}%)
|
|
74
|
+
- Deferred items: {N}
|
|
75
|
+
- Matrix revision: 1
|
|
76
|
+
|
|
77
|
+
## Candidate Coverage Ledger
|
|
78
|
+
| candidate | category | decision | case_ids | reason |
|
|
79
|
+
|
|
80
|
+
## Cases
|
|
81
|
+
### {module-name}
|
|
82
|
+
| case_id | behavior | design_method | input | expected | test_kind | test_tier | mock | work_mode | test_file | test_method_name | run_command |
|
|
83
|
+
|
|
84
|
+
## Adversarial Cases
|
|
85
|
+
| case_id | behavior | design_method | input | expected | test_kind | test_tier | mock | work_mode | test_file | test_method_name | run_command |
|
|
86
|
+
|
|
87
|
+
## Deferred Items
|
|
88
|
+
| case_id | behavior | design_method | reason | deferred_since |
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Post-Generation
|
|
92
|
+
|
|
93
|
+
写入 `test-matrix.md` 后,在 `execution-contract.md` 中添加引用段:
|
|
94
|
+
```markdown
|
|
95
|
+
## Test Matrix
|
|
96
|
+
See `test-matrix.md` for the full test case matrix (附属产物, 独立 hash).
|
|
97
|
+
- Total cases: {N}, Unit: {N}, Integration: {N}, Deferred: {N}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
然后执行 `tf state rebuild <change-dir>` 更新 `test_matrix_hash`。
|
|
101
|
+
|
|
102
|
+
### Hotfix/Tweak Exemption
|
|
103
|
+
|
|
104
|
+
hotfix/tweak workflow 不生成 test-matrix.md(guard 豁免)。设置:
|
|
105
|
+
```bash
|
|
106
|
+
tf state set <change-dir> test_matrix_skipped true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### GLAF4 Java 路由
|
|
110
|
+
|
|
111
|
+
当项目技术栈为 GLAF4 Java(Spring Boot / JUnit 5 / Mockito)时,提示用户是否调用 `glaf4-test:glaf4-tests` 做精细矩阵设计。用户同意后由 glaf4-tests design stage 生成 `test-matrix.json`,再转换为 team-flow 格式的 `test-matrix.md`。
|
|
112
|
+
|
|
37
113
|
## Approval Model (DP-3)
|
|
38
114
|
|
|
39
115
|
After drafting: summarize handoff rules, identify ambiguity, flag unmapped requirements, ask user to approve explicitly. After approval:
|
|
@@ -53,6 +129,8 @@ Generate minimal contract: Intent Lock (one sentence), Task List (numbered), App
|
|
|
53
129
|
|
|
54
130
|
## Guardrails
|
|
55
131
|
|
|
132
|
+
- **状态字段禁写(v0.30.0)**:仅写本 skill 的 `dp_3_*` 决策字段;**MUST NOT** 修改 `state`/`workflow` 核心字段——状态转换由主代理经 `tf state transition` 执行。`tf state init` 只创建状态文件,不改 `state` 值(来源:workflow-feedback 2026-08-01)。
|
|
133
|
+
|
|
56
134
|
- Do not continue to implementation if ambiguity remains
|
|
57
135
|
- Do not approve the contract on the user's behalf
|
|
58
136
|
- Do not skip the contract because planning docs look complete
|
|
@@ -52,6 +52,8 @@ Once DP-1 is recorded, hand off to `spec-writer`.
|
|
|
52
52
|
|
|
53
53
|
## Anti-Patterns
|
|
54
54
|
|
|
55
|
+
- **修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段**(v0.30.0 禁止):状态转换是主代理经 `tf state transition` 的专有职责;need-explorer 只写自己的 `dp_1_*` 决策字段(来源:workflow-feedback 2026-08-01)。
|
|
56
|
+
|
|
55
57
|
- **Skipping exploration**: "Simple" changes have scope too. Five minutes of exploration prevents two hours of rework.
|
|
56
58
|
- **Proposing solutions before clarifying**: If the user says "add caching," first ask what problem caching solves.
|
|
57
59
|
- **Exploring indefinitely**: Stop when change name, problem statement, scope, non-goals, success criteria, and decomposition decision are all clear.
|
|
@@ -34,6 +34,21 @@ Run full test suite. Record total/passed/failed/skipped. Zero failures = PASS.
|
|
|
34
34
|
### Step 2: Completeness
|
|
35
35
|
Compare contract batches against actual diff. Every SHALL/MUST must have implementation evidence. Missing = Critical severity.
|
|
36
36
|
|
|
37
|
+
### Step 2b: Test Matrix Reconciliation (conditional, v0.12 §44.4)
|
|
38
|
+
|
|
39
|
+
If `test-matrix.md` exists:
|
|
40
|
+
1. **Statistics**: total cases / implemented / passed
|
|
41
|
+
2. **Candidate Coverage Ledger audit**: any `decision=deferred` without reasonable reason?
|
|
42
|
+
3. **Complexity tier check**: cases per module meet minimum (trivial≥3 / medium≥5 / complex≥7)?
|
|
43
|
+
4. **Verdict**:
|
|
44
|
+
- Matrix coverage = 100% AND all cases pass → **PASS**
|
|
45
|
+
- Matrix coverage ≥ 90% with reasonable deferred items → **CONDITIONAL (WARN)**
|
|
46
|
+
- Matrix coverage < 90% OR unexplained gaps → **FAIL**
|
|
47
|
+
|
|
48
|
+
If `test-matrix.md` does NOT exist → **SKIP** (legacy change compatibility).
|
|
49
|
+
|
|
50
|
+
Add a report row: `| Test Matrix | PASS/FAIL/WARN/SKIP | [reconciliation summary] |`
|
|
51
|
+
|
|
37
52
|
### Step 3: Coherence
|
|
38
53
|
Compare design decisions against code. Check naming consistency. Inconsistencies = IMPORTANT.
|
|
39
54
|
|
|
@@ -67,6 +82,8 @@ If an `e2e/` suite exists for the change, fold its report into verification (see
|
|
|
67
82
|
|
|
68
83
|
## Final Checks
|
|
69
84
|
|
|
85
|
+
**⛔ 状态字段禁写(v0.30.0)**:仅写本 skill 的 `dp_6_*`/`dp_7_*` 决策字段与 `test_result`;**MUST NOT** 修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段——closing 转换由主代理经 `tf state transition` 执行(来源:workflow-feedback 2026-08-01)。
|
|
86
|
+
|
|
70
87
|
- Tests passing? (cite command and output)
|
|
71
88
|
- All batches complete? (cite batch status)
|
|
72
89
|
- Scope added without artifact updates?
|
|
@@ -113,7 +130,7 @@ tf arch-merge <change-dir>
|
|
|
113
130
|
|
|
114
131
|
This merges `architecture/{architecture,database,api}.md` and `architecture/sql/` into the global architecture docs. Skip silently when `architecture/` does not exist (architecture-design was `skipped`).
|
|
115
132
|
|
|
116
|
-
**Execution order (mandatory)**: `arch-merge` → `prototype-sync` → `compound promotion`. Do not parallelise — global docs must not be in a half-updated state.
|
|
133
|
+
**Execution order (mandatory, v0.12 §43.4)**: `arch-merge` → `prototype-sync` → `test-merge` → `compound promotion`. Do not parallelise — global docs must not be in a half-updated state.
|
|
117
134
|
|
|
118
135
|
### Prototype Sync (v0.5)
|
|
119
136
|
|
|
@@ -123,12 +140,30 @@ After `arch-merge` completes, run prototype-sync to merge UX deltas back to the
|
|
|
123
140
|
tf prototype-sync <change-dir>
|
|
124
141
|
```
|
|
125
142
|
|
|
126
|
-
**Write-back order (mandatory)**: `arch-merge` → `prototype-sync` → `compound promotion` must be executed **sequentially** within the same change closing. Do not run them in parallel — the global `docs/architecture
|
|
143
|
+
**Write-back order (mandatory, v0.12 §43.4)**: `arch-merge` → `prototype-sync` → `test-merge` → `compound promotion` must be executed **sequentially** within the same change closing. Do not run them in parallel — the global `docs/architecture/`, `prototype/`, and `docs/test-ledger/` must not be in a half-updated state when the next change grounds on them.
|
|
127
144
|
|
|
128
145
|
If `prototype-sync` reports conflicts, list them in the closing summary and flag for manual resolution. Do not block closing on prototype-sync conflicts (advisory level).
|
|
129
146
|
|
|
130
147
|
**Execution verification(v0.24.0)**:`prototype-sync` 命令执行后,检查其 stdout 输出确认合并完成(输出含 `merged`/`no UX delta`/`conflicts` 之一)。若命令未执行或执行失败,Step 5 Report 的 `Prototype sync` 行必须标注 `SKIPPED` 或 `FAILED`,并在 closing summary 中说明原因。**禁止在 prototype-sync 未执行时将 Prototype sync 行标注为已完成**。
|
|
131
148
|
|
|
149
|
+
### Test Merge (v0.12 §43)
|
|
150
|
+
|
|
151
|
+
After `prototype-sync` completes, run test-merge to write test matrix results back to the global test ledger:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
tf test-merge <change-dir>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This merges `test-matrix.md` into `docs/test-ledger/`:
|
|
158
|
+
- **mergeBaselines**: extract cases by module, incrementally update `baselines/{module}.md`
|
|
159
|
+
- **resolveDeferred**: new cases covering old deferred items → remove from Deferred
|
|
160
|
+
- **appendChangelog**: archive test-matrix.md → `changelog/{change-id}.md`
|
|
161
|
+
- **rewriteIndex**: recalculate module/case/deferred counts, rewrite `INDEX.md`
|
|
162
|
+
|
|
163
|
+
Skip silently when `test-matrix.md` does not exist (legacy change or test_matrix_skipped=true).
|
|
164
|
+
|
|
165
|
+
**Execution verification**: check stdout output for `test-merge complete` confirmation. If the command did not execute or failed, Step 5 Report's `Test Matrix` row (from Step 2b) must note the reason.
|
|
166
|
+
|
|
132
167
|
### Compound Promotion (v0.5)
|
|
133
168
|
|
|
134
169
|
During closing, promote change-level learnings to the global solutions library:
|
|
@@ -72,6 +72,8 @@ Run: `tf runtime config --get artifacts.order` — generate in configured order
|
|
|
72
72
|
|
|
73
73
|
## Working Rules
|
|
74
74
|
|
|
75
|
+
**⛔ 状态字段禁写(v0.30.0)**:仅通过 `tf state set` 写本 skill 的 `dp_2_*` 决策字段;**MUST NOT** 修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段——状态转换是主代理(workflow-start)经 `tf state transition` 的专有职责(来源:workflow-feedback 2026-08-01)。
|
|
76
|
+
|
|
75
77
|
**Honor DP-0**: Read `dp_0_decisions`, respect confirmed constraints, don't silently expand scope. Pause on unconfirmed decisions.
|
|
76
78
|
|
|
77
79
|
**Honor Brief (v0.9)**: 若 `change-brief.md` 存在,尊重其 scope 边界与 AC 列表(见 Required Inputs「Change Brief」)——不静默丢弃 brief AC、不静默超出 brief scope;与 plan.md 冲突时以 plan.md 为准并注明。
|
|
@@ -86,6 +88,8 @@ Every requirement must be testable. Use SHALL or MUST. Every requirement must ha
|
|
|
86
88
|
|
|
87
89
|
Optional structured AC tags under a Scenario are supported for E2E extraction (v0.4, design spec ch.16): `##### Exception:` (→ EX AC, ×2), `##### State:` (→ ST AC, ×2), `##### Boundary:` (→ BND AC, ×1). These are **OPTIONAL** — omitting them does NOT fail validation. The `e2e` skill applies dimension-conditional gating (absent dimension = N/A, not 0%) plus keyword fallback (error/invalid/fail/边界), so no spec is forced to add tags.
|
|
88
90
|
|
|
91
|
+
Optional test-dimension tags under a Scenario are supported for test-matrix extraction (v0.12 §44.1): `##### Unit:` (→ unit test hints: equivalence classes, boundary values), `##### Integration:` (→ integration test hints: cross-module, transaction boundaries). These are **OPTIONAL** — omitting them does NOT fail validation. The `contract-builder` extracts matrix skeletons from these tags when present, but does not require them.
|
|
92
|
+
|
|
89
93
|
### design.md
|
|
90
94
|
Must have: Context (current state, constraints, stakeholders), Goals, Decisions (Choice + Rationale + Alternatives considered), Risks And Trade-Offs.
|
|
91
95
|
|
|
@@ -125,7 +129,7 @@ Generate one at a time. Confirm each before next. This prevents scope drift —
|
|
|
125
129
|
- `## Why` > 50 chars, `## What Changes`, `## Scope` (In/Out), `## Impact`, `## Capabilities`, no TBD/TODO
|
|
126
130
|
|
|
127
131
|
### specs/
|
|
128
|
-
- SHALL/MUST for required behavior, `#### Scenario:` with WHEN/THEN per requirement, grouped under delta headers, no contradictions; optional `##### Exception:/State:/Boundary:` sub-tags allowed but NOT required (absent dimension = N/A, not 0%). Regression: a spec containing `##### Exception:` must still pass `npm run validate` (validateDeltaSpec must not reject unknown sub-headings).
|
|
132
|
+
- SHALL/MUST for required behavior, `#### Scenario:` with WHEN/THEN per requirement, grouped under delta headers, no contradictions; optional `##### Exception:/State:/Boundary:` sub-tags allowed but NOT required (absent dimension = N/A, not 0%); optional `##### Unit:/Integration:` sub-tags allowed but NOT required (test-matrix hints for contract-builder). Regression: a spec containing `##### Exception:` must still pass `npm run validate` (validateDeltaSpec must not reject unknown sub-headings).
|
|
129
133
|
|
|
130
134
|
### design.md
|
|
131
135
|
- `## Context`, `## Goals`, `## Decisions` (≥1, with Choice+Rationale+Alternatives), `## Risks And Trade-Offs`
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-strategy
|
|
3
|
+
description: 测试设计方法论 skill——design_method 选择、分层策略、对抗验证、复杂度分级。build-executor 通过 skills: 预加载。
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Test Strategy
|
|
8
|
+
|
|
9
|
+
测试设计方法论的硬规则。build-executor 通过 `skills: [test-strategy]` 预加载。
|
|
10
|
+
详细说明见 `references/design-methods-detail.md`、`references/complexity-grading.md`、`references/adversarial-patterns.md`。
|
|
11
|
+
|
|
12
|
+
## 1. Design Method 选择规则(三级分层)
|
|
13
|
+
|
|
14
|
+
### 基础级(必选——每个被测目标必须覆盖)
|
|
15
|
+
- **equivalence**: 输入域有有效/无效分类
|
|
16
|
+
- **boundary**: 数字/长度/日期/金额/分页存在边界(6 值法:min-1/min/min+1/max-1/max/max+1)
|
|
17
|
+
- **error**: 业务异常、空值、外部依赖失败
|
|
18
|
+
|
|
19
|
+
### 扩展级(条件触发)
|
|
20
|
+
- **path**: 方法存在多分支(圈复杂度 M = 判定节点+1,用例数 ≥ M)
|
|
21
|
+
- **state**: 对象状态改变或业务规则依赖状态迁移
|
|
22
|
+
- **exception**: 显式覆盖异常类型/消息/框架异常映射
|
|
23
|
+
- **reject**: 业务拒绝、准入失败、权限拒绝
|
|
24
|
+
|
|
25
|
+
### 高级(场景触发)
|
|
26
|
+
- **permission**: API 权限、租户、用户上下文
|
|
27
|
+
- **idempotency**: 重复调用、重复消息、补偿逻辑
|
|
28
|
+
- **concurrency**: 锁、事务、异步消息、并发更新
|
|
29
|
+
- **contract**: 跨模块/跨服务接口契约(Feign、MQ 消息格式、领域事件字段)
|
|
30
|
+
|
|
31
|
+
## 2. 复杂度分级用例数
|
|
32
|
+
|
|
33
|
+
| 复杂度 | 判据 | 最少用例 |
|
|
34
|
+
|--------|------|---------|
|
|
35
|
+
| trivial | is_trivial=true(enum/constant/POJO) | ≥3(仅 equivalence + error,boundary 可省) |
|
|
36
|
+
| medium | 默认(无判据命中) | ≥5 |
|
|
37
|
+
| complex | public_methods>15 或 lines>800 或 圈复杂度>10 或 param_count>6 | ≥7 |
|
|
38
|
+
|
|
39
|
+
保守默认:事实是估算非实测 → 强制 medium 档(≥5)。
|
|
40
|
+
|
|
41
|
+
## 3. 分层策略(测试金字塔比例)
|
|
42
|
+
|
|
43
|
+
- unit(test_tier=unit):70-80% 的 case
|
|
44
|
+
- integration(test_tier=integration):≤30% 的 case
|
|
45
|
+
- e2e:由 e2e skill 独立覆盖,不计入本矩阵
|
|
46
|
+
|
|
47
|
+
## 4. 对抗验证三招(矩阵生成后必检)
|
|
48
|
+
|
|
49
|
+
1. **恶意输入**:至少 1 个 case 覆盖 null/空串/超大值/特殊字符
|
|
50
|
+
2. **并发场景**:涉及锁/事务/异步 → 至少 1 个 concurrency case
|
|
51
|
+
3. **依赖失败**:涉及外部依赖 → 至少 1 个 dependency_failure case(超时/熔断/返回空)
|
|
52
|
+
|
|
53
|
+
## 5. 自检门口诀
|
|
54
|
+
|
|
55
|
+
每个方法至少:**1 正常 + 1 边界 + 1 异常 + 1 null/空**
|
|
56
|
+
|
|
57
|
+
## 6. Schema 强制覆盖(test-matrix.md 校验)
|
|
58
|
+
|
|
59
|
+
1. cases 必须包含至少 1 个 `design_method ∈ {boundary, equivalence}` 的 case
|
|
60
|
+
2. cases 必须包含至少 1 个 `design_method ∈ {error, exception, reject}` 的 case
|
|
61
|
+
3. `complexity_tier=trivial` 时降级:允许只覆盖 equivalence + error
|
|
62
|
+
4. 对抗验证段必须存在(恶意输入/并发/依赖失败三类之一,视目标而定)
|
|
63
|
+
|
|
64
|
+
## 7. work_mode 三种模式
|
|
65
|
+
|
|
66
|
+
| work_mode | 适用场景 | TDD 节奏 |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| **TDD** | 新功能/新行为 | RED→GREEN→REFACTOR |
|
|
69
|
+
| **CHARACTERIZATION** | 遗留代码行为捕获 | 只写不改(不改生产代码) |
|
|
70
|
+
| **REGRESSION** | 缺陷复现+修复 | 先复现再修 |
|
|
Binary file
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Complexity Grading
|
|
2
|
+
|
|
3
|
+
复杂度分级的详细规则。SKILL.md §2 的扩展参考。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 分级标准
|
|
8
|
+
|
|
9
|
+
### trivial(简单)
|
|
10
|
+
|
|
11
|
+
**判据**(命中任一):
|
|
12
|
+
- 纯常量/枚举类(无方法体)
|
|
13
|
+
- POJO/DTO(仅 getter/setter,无业务逻辑)
|
|
14
|
+
- 工具方法的简单委托(`return delegate.doSomething(x)`)
|
|
15
|
+
- 配置文件读取(无校验逻辑)
|
|
16
|
+
|
|
17
|
+
**最少用例数**:≥3
|
|
18
|
+
- equivalence: 1 个正常输入
|
|
19
|
+
- error: 1 个 null/空值
|
|
20
|
+
- boundary: **可省**(trivial 降级特权)
|
|
21
|
+
|
|
22
|
+
**示例**:
|
|
23
|
+
```java
|
|
24
|
+
// ErrorCode.java — 纯枚举
|
|
25
|
+
// OrderDTO.java — 仅 getter/setter
|
|
26
|
+
// StringUtils.isBlank() — 简单委托
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### medium(中等)— 默认
|
|
30
|
+
|
|
31
|
+
**判据**:无 trivial 或 complex 判据命中时,强制 medium。
|
|
32
|
+
|
|
33
|
+
**最少用例数**:≥5
|
|
34
|
+
- equivalence: ≥1 正常 + ≥1 无效
|
|
35
|
+
- boundary: ≥2(至少 1 个下边界 + 1 个上边界)
|
|
36
|
+
- error: ≥1
|
|
37
|
+
|
|
38
|
+
### complex(复杂)
|
|
39
|
+
|
|
40
|
+
**判据**(命中任一):
|
|
41
|
+
- public_methods > 15
|
|
42
|
+
- lines > 800(含注释和空行)
|
|
43
|
+
- 圈复杂度 > 10
|
|
44
|
+
- param_count > 6(单个方法参数超过 6 个)
|
|
45
|
+
- 涉及 ≥3 个外部依赖交互
|
|
46
|
+
- 包含状态机(≥4 个状态)
|
|
47
|
+
|
|
48
|
+
**最少用例数**:≥7
|
|
49
|
+
- equivalence: ≥2 正常 + ≥2 无效
|
|
50
|
+
- boundary: ≥3(至少含 1 个 6 值法完整覆盖)
|
|
51
|
+
- error: ≥1
|
|
52
|
+
- path: ≥1(如果有分支)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 2. 圈复杂度计算方法
|
|
57
|
+
|
|
58
|
+
### 手动计算
|
|
59
|
+
|
|
60
|
+
从 1 开始(方法本身的 1 条直线执行路径),每遇到以下结构 +1:
|
|
61
|
+
|
|
62
|
+
| 结构 | 增量 |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `if` / `else if` | +1 |
|
|
65
|
+
| `switch` 每个 `case`(含 `default`) | +1 per case |
|
|
66
|
+
| `for` / `while` / `do-while` | +1 |
|
|
67
|
+
| `&&` / `||` 短路运算 | +1 per operator |
|
|
68
|
+
| `catch` | +1 |
|
|
69
|
+
| `?:`(三元表达式) | +1 |
|
|
70
|
+
|
|
71
|
+
**示例**:
|
|
72
|
+
```java
|
|
73
|
+
public void process(Order order) { // 1
|
|
74
|
+
if (order == null) { ... } // +1 = 2
|
|
75
|
+
if (order.getStatus() == PAID // +1 = 3
|
|
76
|
+
&& order.getAmount() > 1000) { ... } // +1 = 4
|
|
77
|
+
for (Item item : order.getItems()) { // +1 = 5
|
|
78
|
+
if (item.isDiscounted()) { ... } // +1 = 6
|
|
79
|
+
switch (item.getType()) {
|
|
80
|
+
case PHYSICAL: ... break; // +1 = 7
|
|
81
|
+
case DIGITAL: ... break; // +1 = 8
|
|
82
|
+
default: ... // +1 = 9
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 圈复杂度 = 9 → medium 档(未超 10)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 工具辅助
|
|
90
|
+
|
|
91
|
+
| 语言 | 工具 | 命令 |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Java | Checkstyle / PMD | `mvn checkstyle:check` / `pmd check` |
|
|
94
|
+
| Java | SonarQube | 自动扫描 |
|
|
95
|
+
| TypeScript | complexity-report | `npx complexity-report src/` |
|
|
96
|
+
| Python | radon | `radon cc src/` |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 3. 校准规则
|
|
101
|
+
|
|
102
|
+
### 保守默认
|
|
103
|
+
|
|
104
|
+
- 事实是估算非实测 → 不确定时强制 medium 档(≥5)
|
|
105
|
+
- 宁可多做不可漏做 → 边界 case 优先于 happy path
|
|
106
|
+
|
|
107
|
+
### 方法拆分时的处理
|
|
108
|
+
|
|
109
|
+
如果一个方法被拆分为多个小方法:
|
|
110
|
+
- 拆分前:complex(圈复杂度 12)
|
|
111
|
+
- 拆分后:每个子方法 medium(圈复杂度 4-6)
|
|
112
|
+
- **但**:拆分前的 complex 级用例数仍需保留(不因拆分而降级)
|
|
113
|
+
|
|
114
|
+
### 组合方法的计算
|
|
115
|
+
|
|
116
|
+
如果类有多个 public 方法:
|
|
117
|
+
- 每个方法独立计算复杂度
|
|
118
|
+
- 类的总复杂度 = 各方法圈复杂度之和
|
|
119
|
+
- 类的用例数 = 各方法用例数之和(去重共享的 setup/teardown case)
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 4. 与 test-matrix.md 的关联
|
|
124
|
+
|
|
125
|
+
在 test-matrix.md 的 `## Summary` 段中标注每个模块的复杂度分级:
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
## Summary
|
|
129
|
+
- Total cases: 35
|
|
130
|
+
- Modules covered: 4
|
|
131
|
+
- OrderService: complex (圈复杂度 14, ≥7 cases)
|
|
132
|
+
- PaymentValidator: medium (圈复杂度 6, ≥5 cases)
|
|
133
|
+
- ErrorCode: trivial (纯枚举, ≥3 cases)
|
|
134
|
+
- OrderConverter: trivial (POJO 映射, ≥3 cases)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
contract-builder 在生成矩阵时,必须为每个模块标注复杂度分级,作为用例数下限的判据。
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Design Methods Detail
|
|
2
|
+
|
|
3
|
+
10+1 种测试设计方法的详细说明。SKILL.md §1 的扩展参考。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 基础级(必选)
|
|
8
|
+
|
|
9
|
+
### equivalence(等价类划分)
|
|
10
|
+
|
|
11
|
+
**触发条件**:输入域有有效/无效分类。
|
|
12
|
+
|
|
13
|
+
**方法**:
|
|
14
|
+
1. 识别输入参数的有效等价类和无效等价类
|
|
15
|
+
2. 每个等价类取 1 个代表值
|
|
16
|
+
3. 有效类 → 验证正常行为;无效类 → 验证拒绝/异常
|
|
17
|
+
|
|
18
|
+
**示例(Java)**:
|
|
19
|
+
```java
|
|
20
|
+
// 有效等价类:validOrderId (正整数)
|
|
21
|
+
// 无效等价类:null, 0, -1, 超过 MAX_LONG
|
|
22
|
+
@Test void shouldFindOrder_whenValidId() { ... }
|
|
23
|
+
@Test void shouldThrow_whenNullId() { ... }
|
|
24
|
+
@Test void shouldThrow_whenNegativeId() { ... }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### boundary(边界值分析)
|
|
28
|
+
|
|
29
|
+
**触发条件**:数字/长度/日期/金额/分页存在边界。
|
|
30
|
+
|
|
31
|
+
**6 值法**:对每个边界取 min-1 / min / min+1 / max-1 / max / max+1
|
|
32
|
+
|
|
33
|
+
| 边界类型 | 示例(金额 0.01 ~ 999999.99) |
|
|
34
|
+
|---|---|
|
|
35
|
+
| min-1 | 0.00 → 拒绝 |
|
|
36
|
+
| min | 0.01 → 接受(最小合法) |
|
|
37
|
+
| min+1 | 0.02 → 接受 |
|
|
38
|
+
| max-1 | 999999.98 → 接受 |
|
|
39
|
+
| max | 999999.99 → 接受(最大合法) |
|
|
40
|
+
| max+1 | 1000000.00 → 拒绝 |
|
|
41
|
+
|
|
42
|
+
**日期边界特殊处理**:
|
|
43
|
+
- 闰年:2024-02-29 / 2025-02-28
|
|
44
|
+
- 月末/月初:1月31日 → 2月1日
|
|
45
|
+
- 时区切换:UTC+8 的 23:59 vs UTC 的 15:59
|
|
46
|
+
|
|
47
|
+
### error(错误/异常路径)
|
|
48
|
+
|
|
49
|
+
**触发条件**:业务异常、空值、外部依赖失败。
|
|
50
|
+
|
|
51
|
+
**必须覆盖的三类**:
|
|
52
|
+
1. **参数校验错误**:null、空串、格式错误
|
|
53
|
+
2. **业务规则违反**:库存不足、余额不够、重复操作
|
|
54
|
+
3. **外部依赖失败**:DB 连接超时、HTTP 5xx、MQ 消费失败
|
|
55
|
+
|
|
56
|
+
**示例**:
|
|
57
|
+
```java
|
|
58
|
+
@Test void shouldThrowBizException_whenInsufficientStock() { ... }
|
|
59
|
+
@Test void shouldReturnEmpty_whenDbReturnsNull() { ... }
|
|
60
|
+
@Test void shouldRetry_whenExternalApiTimeout() { ... }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 扩展级(条件触发)
|
|
66
|
+
|
|
67
|
+
### path(路径覆盖)
|
|
68
|
+
|
|
69
|
+
**触发条件**:方法存在多分支。
|
|
70
|
+
|
|
71
|
+
**圈复杂度计算**:M = 判定节点数 + 1
|
|
72
|
+
- `if` → +1
|
|
73
|
+
- `else if` → +1
|
|
74
|
+
- `switch` 每个 `case` → +1
|
|
75
|
+
- `for` / `while` → +1
|
|
76
|
+
- `&&` / `||` 短路运算 → +1
|
|
77
|
+
|
|
78
|
+
**用例数 ≥ M**。示例:M=4(1 个 if + 1 个 switch 3-case)→ ≥4 个 case。
|
|
79
|
+
|
|
80
|
+
### state(状态迁移)
|
|
81
|
+
|
|
82
|
+
**触发条件**:对象状态改变或业务规则依赖状态迁移。
|
|
83
|
+
|
|
84
|
+
**方法**:
|
|
85
|
+
1. 画出状态迁移图(初始态 → 中间态 → 终态)
|
|
86
|
+
2. 每条迁移边至少 1 个 case
|
|
87
|
+
3. 非法迁移(如 CLOSED → PROCESSING)→ 1 个 reject case
|
|
88
|
+
|
|
89
|
+
**示例(订单状态机)**:
|
|
90
|
+
```
|
|
91
|
+
CREATED → PAID → SHIPPED → DELIVERED → CLOSED
|
|
92
|
+
↓ ↑
|
|
93
|
+
CANCELLED ←──────────────┘ (仅 PAID 前可取消)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### exception(异常覆盖)
|
|
97
|
+
|
|
98
|
+
**触发条件**:显式覆盖异常类型/消息/框架异常映射。
|
|
99
|
+
|
|
100
|
+
**必须验证**:
|
|
101
|
+
1. 异常类型是否正确(BusinessException vs SystemException)
|
|
102
|
+
2. 异常消息是否包含上下文(errorCode + 参数值)
|
|
103
|
+
3. 框架异常映射(Spring 的 `@ResponseStatus` → HTTP 状态码)
|
|
104
|
+
|
|
105
|
+
### reject(业务拒绝)
|
|
106
|
+
|
|
107
|
+
**触发条件**:业务拒绝、准入失败、权限拒绝。
|
|
108
|
+
|
|
109
|
+
**与 error 的区别**:error 是"系统出了问题",reject 是"系统正确地拒绝了"。
|
|
110
|
+
|
|
111
|
+
**示例**:
|
|
112
|
+
```java
|
|
113
|
+
@Test void shouldReject_whenOrderAlreadyClosed() { ... }
|
|
114
|
+
@Test void shouldReject_whenUserNotInWhitelist() { ... }
|
|
115
|
+
@Test void shouldReject_whenDuplicateRequest() { ... }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 高级(场景触发)
|
|
121
|
+
|
|
122
|
+
### permission(权限控制)
|
|
123
|
+
|
|
124
|
+
**触发条件**:API 权限、租户、用户上下文。
|
|
125
|
+
|
|
126
|
+
**覆盖维度**:
|
|
127
|
+
1. 角色权限:ADMIN / USER / GUEST / ANONYMOUS
|
|
128
|
+
2. 租户隔离:租户 A 不能访问租户 B 的数据
|
|
129
|
+
3. 数据权限:只能操作自己创建的资源
|
|
130
|
+
|
|
131
|
+
### idempotency(幂等性)
|
|
132
|
+
|
|
133
|
+
**触发条件**:重复调用、重复消息、补偿逻辑。
|
|
134
|
+
|
|
135
|
+
**验证模式**:
|
|
136
|
+
1. 调用 N 次 → 效果等同于调用 1 次
|
|
137
|
+
2. MQ 重复消费 → 不重复处理
|
|
138
|
+
3. 补偿操作 → 正向 + 逆向 = 无净效果
|
|
139
|
+
|
|
140
|
+
**示例**:
|
|
141
|
+
```java
|
|
142
|
+
@Test void shouldNotDuplicateOrder_whenRetryCreate() {
|
|
143
|
+
var first = orderService.create(request);
|
|
144
|
+
var second = orderService.create(request);
|
|
145
|
+
assertThat(second.getId()).isEqualTo(first.getId());
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### concurrency(并发安全)
|
|
150
|
+
|
|
151
|
+
**触发条件**:锁、事务、异步消息、并发更新。
|
|
152
|
+
|
|
153
|
+
**验证模式**:
|
|
154
|
+
1. 乐观锁冲突 → 重试或拒绝
|
|
155
|
+
2. 分布式锁 → 同一时刻只有一个执行者
|
|
156
|
+
3. 事务隔离 → 读未提交 / 读已提交 / 可重复读
|
|
157
|
+
4. 异步消息 → 最终一致性
|
|
158
|
+
|
|
159
|
+
### contract(接口契约)
|
|
160
|
+
|
|
161
|
+
**触发条件**:跨模块/跨服务接口契约。
|
|
162
|
+
|
|
163
|
+
**覆盖维度**:
|
|
164
|
+
1. Feign 客户端:请求/响应格式与 provider 一致
|
|
165
|
+
2. MQ 消息:字段名/类型/必填项
|
|
166
|
+
3. 领域事件:事件名/载荷/版本
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 派生字段:test_tier
|
|
171
|
+
|
|
172
|
+
从 `test_kind` 派生 `test_tier`(语言无关的粗粒度分类):
|
|
173
|
+
|
|
174
|
+
| test_kind 值 | test_tier |
|
|
175
|
+
|---|---|
|
|
176
|
+
| pure_unit, mockito_unit, spring_assisted_unit | unit |
|
|
177
|
+
| vitest_unit, vue_test_utils_mount | unit |
|
|
178
|
+
| api_mockmvc_standalone, api_mockmvc_slice, api_mockmvc_boot | integration |
|
|
179
|
+
| service_social, repository_h2 | integration |
|
|
180
|
+
| rabbitmq_social, redis_social | integration |
|
|
181
|
+
| external_api_stub, test_infrastructure | integration |
|
|
182
|
+
|
|
183
|
+
**用途**:test_tier 用于统计和 CI 分级;test_kind 用于路由到正确的编写模板。
|
|
@@ -48,6 +48,10 @@ S1 只做编排动作(需求选择、存在性检查、路径判断、阻塞
|
|
|
48
48
|
|
|
49
49
|
工作流模式复利(L2):S1 路由时额外注入历史 `workflow_pattern` top-3(confidence ≥ 0.5)。详见 state-model.md「工作流模式复利 L2」。
|
|
50
50
|
|
|
51
|
+
## 测试台账注入(v0.12 §43.5,advisory 级)
|
|
52
|
+
|
|
53
|
+
读取 `docs/test-ledger/INDEX.md`(如存在),注入 `coverage_status=partial` 的模块列表。新 change 涉及这些模块时,提示「有未解决的 deferred 测试项,本次可考虑解决」。读取失败时静默跳过,不阻断。
|
|
54
|
+
|
|
51
55
|
## 路由结果显式呈现(强制,B3)
|
|
52
56
|
|
|
53
57
|
路由判断后**必须**向用户确认,路由是建议而非决定:
|