specflow-cc 1.11.1 → 1.12.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/CHANGELOG.md +39 -0
- package/agents/impl-reviewer.md +48 -0
- package/agents/spec-auditor.md +52 -0
- package/agents/spec-creator.md +26 -0
- package/agents/spec-executor-worker.md +19 -0
- package/agents/spec-executor.md +32 -1
- package/commands/sf/init.md +77 -0
- package/package.json +1 -1
- package/templates/project.md +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,45 @@ All notable changes to SpecFlow will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.12.0] - 2026-02-10
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Language Profiles** — optional, per-language configuration in PROJECT.md that adapts all agents to language-specific needs
|
|
13
|
+
- `/sf:init` auto-detects language from `Cargo.toml` (Rust), `go.mod` (Go), `tsconfig.json` (TypeScript), `pyproject.toml` (Python)
|
|
14
|
+
- Generates `## Language Profile` section in PROJECT.md with build/lint/test commands, max files per spec, compilation gate, and trait-first settings
|
|
15
|
+
- Projects without a detected language remain fully language-agnostic (backward-compatible)
|
|
16
|
+
|
|
17
|
+
- **Compilation gates** — incremental build verification during implementation (Rust, Go)
|
|
18
|
+
- `spec-executor` and `spec-executor-worker` run `build_check` command after each file or tightly coupled group
|
|
19
|
+
- Build failures auto-fixed before proceeding (Rule 3: blocking issues)
|
|
20
|
+
- Lint check runs at end of implementation scope
|
|
21
|
+
- New `build_check` field in worker JSON result protocol
|
|
22
|
+
|
|
23
|
+
- **Trait-first enforcement** — compiled languages require type/trait design before implementation
|
|
24
|
+
- `spec-creator` mandates G1/Wave 1 as types-only when `Trait-first: Yes`
|
|
25
|
+
- `spec-auditor` validates trait-first compliance (Critical if G1 mixes traits and implementation)
|
|
26
|
+
- Prevents cascading rework from wrong trait boundaries in Rust/Go
|
|
27
|
+
|
|
28
|
+
- **Language-aware spec sizing** — file count limits adapted per language
|
|
29
|
+
- Rust: 3-5 files max (borrow checker errors cascade)
|
|
30
|
+
- Go: 5-8 files max
|
|
31
|
+
- TypeScript/Python: 8-10 files max
|
|
32
|
+
- `spec-auditor` raises Warning/Critical when file count exceeds language profile limit
|
|
33
|
+
|
|
34
|
+
- **Language-specific review gates** in `impl-reviewer`
|
|
35
|
+
- Runs build, lint, and test commands from profile as review gates
|
|
36
|
+
- Rust idiom checks: no unnecessary `.clone()`, `?` operator over `.unwrap()`, `unsafe` documentation, `Send + Sync` bounds
|
|
37
|
+
- Go idiom checks: error returns over panics, interfaces accepted/structs returned, context propagation
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- `templates/project.md` — added optional Language Profile section
|
|
42
|
+
- `spec-auditor` — added Step 3.10 (Language Profile Check) with 5 sub-checks and scope threshold override
|
|
43
|
+
- `spec-creator` — added language-specific sizing table and trait-first override in task group generation
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
8
47
|
## [1.11.1] - 2026-02-10
|
|
9
48
|
|
|
10
49
|
### Fixed
|
package/agents/impl-reviewer.md
CHANGED
|
@@ -165,6 +165,54 @@ During code review, watch for signals that the specification itself may have bee
|
|
|
165
165
|
|
|
166
166
|
**Note:** This is a safety net, not a primary check. Strategic issues should be caught earlier by `spec-auditor`.
|
|
167
167
|
|
|
168
|
+
### 4.9 Language Profile Check
|
|
169
|
+
|
|
170
|
+
**Detection:** Check if PROJECT.md contains a `## Language Profile` section.
|
|
171
|
+
|
|
172
|
+
**If no Language Profile:** Skip this check.
|
|
173
|
+
|
|
174
|
+
**If Language Profile exists:** Run configured verification commands and check results.
|
|
175
|
+
|
|
176
|
+
**4.9.1 Build Check:**
|
|
177
|
+
Run `Build check` command from profile (e.g., `cargo check`, `go build ./...`):
|
|
178
|
+
```bash
|
|
179
|
+
{build_check_command}
|
|
180
|
+
```
|
|
181
|
+
- Exit 0 → ✓ Passed
|
|
182
|
+
- Non-zero → **Critical**: "Build check failed: {error output}"
|
|
183
|
+
|
|
184
|
+
**4.9.2 Lint Check:**
|
|
185
|
+
Run `Lint` command from profile (e.g., `cargo clippy -- -D warnings`):
|
|
186
|
+
```bash
|
|
187
|
+
{lint_command}
|
|
188
|
+
```
|
|
189
|
+
- Exit 0 → ✓ Passed
|
|
190
|
+
- Non-zero → **Major**: "Lint check failed: {warning count} warnings/errors"
|
|
191
|
+
|
|
192
|
+
**4.9.3 Test Check:**
|
|
193
|
+
Run `Test` command from profile (e.g., `cargo test`):
|
|
194
|
+
```bash
|
|
195
|
+
{test_command}
|
|
196
|
+
```
|
|
197
|
+
- Exit 0 → ✓ Passed
|
|
198
|
+
- Non-zero → **Critical**: "Tests failed: {failure summary}"
|
|
199
|
+
|
|
200
|
+
**4.9.4 Language-Specific Idiom Check:**
|
|
201
|
+
|
|
202
|
+
For **Rust** (Language = Rust):
|
|
203
|
+
- [ ] No unnecessary `.clone()` calls — prefer borrowing
|
|
204
|
+
- [ ] Error handling uses `?` operator and `Result<T, E>` — not `.unwrap()` or `.expect()` in production code
|
|
205
|
+
- [ ] `unsafe` blocks have safety invariant comments
|
|
206
|
+
- [ ] Proper `Send + Sync` bounds on trait objects
|
|
207
|
+
- [ ] No `Box<dyn Any>` type erasure where concrete types work
|
|
208
|
+
|
|
209
|
+
For **Go** (Language = Go):
|
|
210
|
+
- [ ] Errors returned, not panicked
|
|
211
|
+
- [ ] Interfaces accepted, structs returned
|
|
212
|
+
- [ ] Context propagation (`ctx context.Context` as first param)
|
|
213
|
+
|
|
214
|
+
If idiom violations found: add as **Major** issues with specific file:line references.
|
|
215
|
+
|
|
168
216
|
## Step 5: Categorize Findings
|
|
169
217
|
|
|
170
218
|
Organize into:
|
package/agents/spec-auditor.md
CHANGED
|
@@ -415,6 +415,57 @@ Check if spec includes items marked as "Out of Scope" or "Deferred" in PROJECT.m
|
|
|
415
415
|
**If compliant:**
|
|
416
416
|
- Add to audit output: "Project compliance: ✓ Honors PROJECT.md decisions"
|
|
417
417
|
|
|
418
|
+
## Step 3.10: Language Profile Check
|
|
419
|
+
|
|
420
|
+
**Detection:** Check if PROJECT.md contains a `## Language Profile` section.
|
|
421
|
+
|
|
422
|
+
**If no Language Profile section:** Skip this check entirely.
|
|
423
|
+
|
|
424
|
+
**If Language Profile exists:** Parse settings and validate spec compliance.
|
|
425
|
+
|
|
426
|
+
### 3.10.1 File Count Check
|
|
427
|
+
|
|
428
|
+
Extract `Max files per spec` from profile. Count total files to create + modify in spec.
|
|
429
|
+
|
|
430
|
+
| Condition | Action |
|
|
431
|
+
|-----------|--------|
|
|
432
|
+
| Files ≤ max | ✓ OK |
|
|
433
|
+
| Files = max + 1-2 | **Warning**: "File count ({N}) slightly exceeds language profile limit ({max}). Consider splitting." |
|
|
434
|
+
| Files > max + 2 | **Critical**: "File count ({N}) significantly exceeds language profile limit ({max}). Must split with `/sf:split`." |
|
|
435
|
+
|
|
436
|
+
### 3.10.2 Trait-First Check
|
|
437
|
+
|
|
438
|
+
If `Trait-first: Yes` AND spec complexity is medium or large:
|
|
439
|
+
|
|
440
|
+
- Check if Implementation Tasks section exists
|
|
441
|
+
- If yes: verify G1 (Wave 1) contains ONLY types/traits/interfaces, not implementation
|
|
442
|
+
- If G1 mixes traits and implementation: **Critical**: "Trait-first violation: G1 must contain only types/traits/interfaces. Implementation must be in Wave 2+."
|
|
443
|
+
- If no Implementation Tasks: **Warning**: "Trait-first language requires explicit task grouping for medium/large specs. Recommend adding Implementation Tasks with types in G1."
|
|
444
|
+
|
|
445
|
+
### 3.10.3 Compilation Gate Awareness
|
|
446
|
+
|
|
447
|
+
If `Compilation gate: Yes`:
|
|
448
|
+
|
|
449
|
+
- Verify task groups are small enough for incremental compilation checks
|
|
450
|
+
- If any single task group modifies >3 files: **Warning**: "Large task group ({N} files) with compilation gate. Consider splitting into smaller groups for incremental `build_check` verification."
|
|
451
|
+
|
|
452
|
+
### 3.10.4 Scope Threshold Override
|
|
453
|
+
|
|
454
|
+
If Language Profile exists, override default Scope Sanity Thresholds:
|
|
455
|
+
|
|
456
|
+
| Metric | Default | With Language Profile |
|
|
457
|
+
|--------|---------|---------------------|
|
|
458
|
+
| Files/plan (Blocker) | 15+ | `Max files per spec` from profile |
|
|
459
|
+
| Tasks/plan (Warning) | 4 | 3 (if `Trait-first: Yes`) |
|
|
460
|
+
|
|
461
|
+
### 3.10.5 Language Profile Verdict
|
|
462
|
+
|
|
463
|
+
**If all checks pass:**
|
|
464
|
+
- Add to audit output: "Language profile: ✓ Compliant with {Language} profile"
|
|
465
|
+
|
|
466
|
+
**If warnings or critical issues found:**
|
|
467
|
+
- Add issues to appropriate category (Critical/Recommendations)
|
|
468
|
+
|
|
418
469
|
## Step 4: Generate Implementation Tasks (for large specs)
|
|
419
470
|
|
|
420
471
|
If scope is large, generate the Implementation Tasks section:
|
|
@@ -738,6 +789,7 @@ Tip: `/clear` recommended before `/sf:run` — executor needs fresh context
|
|
|
738
789
|
- [ ] Specification fully read
|
|
739
790
|
- [ ] PROJECT.md context loaded
|
|
740
791
|
- [ ] All 10 dimensions evaluated (clarity, completeness, testability, scope, feasibility, architecture, duplication, cognitive load, strategic fit, project compliance)
|
|
792
|
+
- [ ] Language profile checked (if present in PROJECT.md)
|
|
741
793
|
- [ ] Assumptions extracted and impact assessed
|
|
742
794
|
- [ ] Project alignment verified
|
|
743
795
|
- [ ] Project compliance verified (decisions, constraints, out-of-scope)
|
package/agents/spec-creator.md
CHANGED
|
@@ -42,6 +42,26 @@ Good specifications are:
|
|
|
42
42
|
| medium | 50-150k | Multiple files, moderate feature |
|
|
43
43
|
| large | >150k | Many files, complex feature — needs /sf:split |
|
|
44
44
|
|
|
45
|
+
## Language Profile Awareness
|
|
46
|
+
|
|
47
|
+
If PROJECT.md contains a `## Language Profile` section, adapt behavior:
|
|
48
|
+
|
|
49
|
+
**Max files per spec:** If `Max files per spec` is set (e.g., 5 for Rust), use it for complexity estimation. A spec exceeding this limit should be flagged as needing `/sf:split`.
|
|
50
|
+
|
|
51
|
+
**Trait-first:** If `Trait-first: Yes`, for medium and large specs:
|
|
52
|
+
- First task group (G1, Wave 1) MUST be types/traits/interfaces only
|
|
53
|
+
- Implementation groups depend on G1
|
|
54
|
+
- This ensures trait design is audited before implementation begins
|
|
55
|
+
|
|
56
|
+
**Language-specific sizing:**
|
|
57
|
+
|
|
58
|
+
| Language | Max Files | Trait-First | Notes |
|
|
59
|
+
|----------|-----------|-------------|-------|
|
|
60
|
+
| Rust | 3-5 | Yes | Borrow checker errors cascade; smaller specs essential |
|
|
61
|
+
| Go | 5-8 | Yes | Interface design drives implementation |
|
|
62
|
+
| TypeScript | 8-10 | No | Dynamic typing allows larger specs |
|
|
63
|
+
| Python | 8-10 | No | Dynamic typing allows larger specs |
|
|
64
|
+
|
|
45
65
|
</philosophy>
|
|
46
66
|
|
|
47
67
|
<process>
|
|
@@ -136,6 +156,12 @@ Write to `.specflow/specs/SPEC-XXX.md` using the template structure:
|
|
|
136
156
|
- **Medium** and **large** complexity specs: Always include Implementation Tasks section
|
|
137
157
|
- **Small** complexity specs: Optional (skip if only 1-2 files or simple change)
|
|
138
158
|
|
|
159
|
+
**Language Profile Override:**
|
|
160
|
+
If PROJECT.md has `Trait-first: Yes` in Language Profile:
|
|
161
|
+
- G1 (Wave 1) MUST contain ONLY types/traits/interfaces — no implementation
|
|
162
|
+
- All implementation groups MUST depend on G1
|
|
163
|
+
- This is mandatory, not a suggestion — trait design errors cascade in compiled languages
|
|
164
|
+
|
|
139
165
|
**Task Groups:**
|
|
140
166
|
|
|
141
167
|
1. Group related work logically:
|
|
@@ -122,6 +122,22 @@ After implementing, verify:
|
|
|
122
122
|
- Follows project conventions
|
|
123
123
|
- Meets task requirements
|
|
124
124
|
|
|
125
|
+
### 3.2.1 Compilation Gate (Language Profile)
|
|
126
|
+
|
|
127
|
+
If PROJECT.md has `Compilation gate: Yes` in Language Profile:
|
|
128
|
+
|
|
129
|
+
After implementing each file or tightly coupled group, run the `Build check` command:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Example for Rust: cargo check
|
|
133
|
+
# Example for Go: go build ./...
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**If build fails:** fix immediately (Rule 3: Auto-fix blocking issues). Do NOT proceed until current file compiles.
|
|
137
|
+
**If build passes:** continue to next file.
|
|
138
|
+
|
|
139
|
+
At end of all tasks in this group: run `Lint` command if specified in profile (e.g., `cargo clippy -- -D warnings`).
|
|
140
|
+
|
|
125
141
|
### 3.3 Commit
|
|
126
142
|
|
|
127
143
|
Create atomic commit:
|
|
@@ -189,10 +205,13 @@ Output structured JSON for orchestrator:
|
|
|
189
205
|
],
|
|
190
206
|
"deviations": [],
|
|
191
207
|
"self_check": "passed",
|
|
208
|
+
"build_check": "passed",
|
|
192
209
|
"error": null
|
|
193
210
|
}
|
|
194
211
|
```
|
|
195
212
|
|
|
213
|
+
**Note:** `build_check` field is only included when Language Profile has `Compilation gate: Yes`. Values: `"passed"`, `"fixed"` (had to fix compilation errors), `"skipped"` (no language profile).
|
|
214
|
+
|
|
196
215
|
**For segmented execution, add segment fields:**
|
|
197
216
|
|
|
198
217
|
```json
|
package/agents/spec-executor.md
CHANGED
|
@@ -131,6 +131,28 @@ After implementing, verify:
|
|
|
131
131
|
- Meets relevant acceptance criteria
|
|
132
132
|
- Follows project conventions
|
|
133
133
|
|
|
134
|
+
### 4.2.1 Compilation Gate (Language Profile)
|
|
135
|
+
|
|
136
|
+
If PROJECT.md has `Compilation gate: Yes` in Language Profile:
|
|
137
|
+
|
|
138
|
+
After implementing each file or tightly coupled group of files, run the `Build check` command from the profile:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Example for Rust:
|
|
142
|
+
cargo check
|
|
143
|
+
# Example for Go:
|
|
144
|
+
go build ./...
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**If build fails:**
|
|
148
|
+
- Fix the compilation error immediately (Rule 3: Auto-fix blocking issues)
|
|
149
|
+
- Do NOT proceed to next file until current file compiles
|
|
150
|
+
- Track as: `[Rule 3 - Compilation] Fixed {error} in {file}`
|
|
151
|
+
|
|
152
|
+
**If build passes:** continue to next file.
|
|
153
|
+
|
|
154
|
+
This prevents cascading errors — especially critical for Rust where borrow checker errors in file A can mask the real issue in file B.
|
|
155
|
+
|
|
134
156
|
### 4.3 Commit
|
|
135
157
|
|
|
136
158
|
Create atomic commit:
|
|
@@ -191,7 +213,16 @@ For key modifications, verify the change is present:
|
|
|
191
213
|
grep -q "expected_pattern" path/to/modified/file && echo "VERIFIED" || echo "NOT FOUND"
|
|
192
214
|
```
|
|
193
215
|
|
|
194
|
-
**4.
|
|
216
|
+
**4. Language profile checks (if Language Profile exists in PROJECT.md):**
|
|
217
|
+
|
|
218
|
+
Run each configured command and verify it passes:
|
|
219
|
+
- `Lint` command (e.g., `cargo clippy -- -D warnings`) → must exit 0
|
|
220
|
+
- `Test` command (e.g., `cargo test`) → must exit 0
|
|
221
|
+
- `Safety check` command if present (e.g., `cargo miri test`) → must exit 0
|
|
222
|
+
|
|
223
|
+
If any check fails: fix the issue before proceeding (Rule 3).
|
|
224
|
+
|
|
225
|
+
**5. Report self-check result:**
|
|
195
226
|
|
|
196
227
|
- If ALL checks pass: continue to Execution Summary
|
|
197
228
|
- If ANY check fails: **fix the issue** before proceeding, do NOT report success with missing artifacts
|
package/commands/sf/init.md
CHANGED
|
@@ -77,6 +77,83 @@ ls -d **/components/** 2>/dev/null | head -5
|
|
|
77
77
|
ls tsconfig.json 2>/dev/null
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
## Step 4.5: Detect Language Profile
|
|
81
|
+
|
|
82
|
+
Based on Step 2 detection results, determine primary language and generate profile:
|
|
83
|
+
|
|
84
|
+
**Rust** (if `Cargo.toml` found):
|
|
85
|
+
```markdown
|
|
86
|
+
## Language Profile
|
|
87
|
+
|
|
88
|
+
| Setting | Value |
|
|
89
|
+
|---------|-------|
|
|
90
|
+
| Language | Rust |
|
|
91
|
+
| Build check | `cargo check` |
|
|
92
|
+
| Lint | `cargo clippy -- -D warnings` |
|
|
93
|
+
| Test | `cargo test` |
|
|
94
|
+
| Max files per spec | 5 |
|
|
95
|
+
| Compilation gate | Yes — run `cargo check` after each implementation block |
|
|
96
|
+
| Trait-first | Yes — trait/interface design must be in Wave 1 |
|
|
97
|
+
|
|
98
|
+
### Rust-Specific Guidelines
|
|
99
|
+
|
|
100
|
+
- Keep specs to 3-5 files max (borrow checker errors cascade across files)
|
|
101
|
+
- Design traits/interfaces before implementation (wrong trait boundaries force rewrites)
|
|
102
|
+
- Run `cargo check` after every file change, not just at the end
|
|
103
|
+
- Prefer `Result<T, E>` over `unwrap()`/`expect()` in production code
|
|
104
|
+
- Document `unsafe` blocks with safety invariants
|
|
105
|
+
- Use `cargo clippy` as mandatory quality gate
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Go** (if `go.mod` found):
|
|
109
|
+
```markdown
|
|
110
|
+
## Language Profile
|
|
111
|
+
|
|
112
|
+
| Setting | Value |
|
|
113
|
+
|---------|-------|
|
|
114
|
+
| Language | Go |
|
|
115
|
+
| Build check | `go build ./...` |
|
|
116
|
+
| Lint | `golangci-lint run` |
|
|
117
|
+
| Test | `go test ./...` |
|
|
118
|
+
| Max files per spec | 8 |
|
|
119
|
+
| Compilation gate | Yes — run `go build ./...` after each implementation block |
|
|
120
|
+
| Trait-first | Yes — interface design must be in Wave 1 |
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**TypeScript** (if `tsconfig.json` found):
|
|
124
|
+
```markdown
|
|
125
|
+
## Language Profile
|
|
126
|
+
|
|
127
|
+
| Setting | Value |
|
|
128
|
+
|---------|-------|
|
|
129
|
+
| Language | TypeScript |
|
|
130
|
+
| Build check | `npx tsc --noEmit` |
|
|
131
|
+
| Lint | `npx eslint .` |
|
|
132
|
+
| Test | `pnpm test` |
|
|
133
|
+
| Max files per spec | 10 |
|
|
134
|
+
| Compilation gate | No |
|
|
135
|
+
| Trait-first | No |
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Python** (if `pyproject.toml` or `setup.py` found):
|
|
139
|
+
```markdown
|
|
140
|
+
## Language Profile
|
|
141
|
+
|
|
142
|
+
| Setting | Value |
|
|
143
|
+
|---------|-------|
|
|
144
|
+
| Language | Python |
|
|
145
|
+
| Build check | — |
|
|
146
|
+
| Lint | `ruff check .` |
|
|
147
|
+
| Test | `pytest` |
|
|
148
|
+
| Max files per spec | 10 |
|
|
149
|
+
| Compilation gate | No |
|
|
150
|
+
| Trait-first | No |
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**If no recognized language detected:** omit Language Profile section entirely.
|
|
154
|
+
|
|
155
|
+
Include the generated profile in Step 6 (Generate PROJECT.md) before the closing `---` line.
|
|
156
|
+
|
|
80
157
|
## Step 5: Create .specflow Directory
|
|
81
158
|
|
|
82
159
|
```bash
|
package/package.json
CHANGED
package/templates/project.md
CHANGED
|
@@ -35,5 +35,19 @@
|
|
|
35
35
|
- [Constraint 1: e.g., Must work offline]
|
|
36
36
|
- [Constraint 2]
|
|
37
37
|
|
|
38
|
+
## Language Profile
|
|
39
|
+
|
|
40
|
+
[Optional — auto-generated by /sf:init based on detected language. Agents use this to adapt spec sizing, compilation gates, and review checks. Remove this section for language-agnostic behavior.]
|
|
41
|
+
|
|
42
|
+
| Setting | Value |
|
|
43
|
+
|---------|-------|
|
|
44
|
+
| Language | [e.g., Rust, TypeScript, Python, Go] |
|
|
45
|
+
| Build check | [e.g., `cargo check`, `npx tsc --noEmit`] |
|
|
46
|
+
| Lint | [e.g., `cargo clippy -- -D warnings`, `npx eslint .`] |
|
|
47
|
+
| Test | [e.g., `cargo test`, `pnpm test`] |
|
|
48
|
+
| Max files per spec | [e.g., 5 for Rust, 10 for TypeScript] |
|
|
49
|
+
| Compilation gate | [Yes/No — run build check after each implementation block] |
|
|
50
|
+
| Trait-first | [Yes/No — require trait/interface design in Wave 1] |
|
|
51
|
+
|
|
38
52
|
---
|
|
39
53
|
*Generated by SpecFlow on [date]*
|