requirements-traceability
Build and verify the AC ↔ tasks ↔ tests ↔ code symbols ↔ gates traceability matrix in `07a-traceability.md`. Use when validating that no AC is uncovered and no test is orphaned.
SKILL.md.claude/skills/requirements-traceability/SKILL.md
GitHubRequirements traceability
What gets traced
For each AC-NNN from 01-spec.md:
- The list of
T-NNNtasks that implement it (04-tasks.md). - The list of test methods that assert it (
@Tag("AC-NNN")or@DisplayName("AC-NNN: …")). - The list of production code symbols (FQ method names) touched by those tasks' diffs.
- The list of harness gates that ran on those symbols.
For each test method:
- The AC it claims to assert.
- The task that introduced it.
For each production symbol changed in the diff:
- At least one test that covers it (else flagged "orphan code").
Building the matrix
spring-validator runs .github/scripts/traceability.sh which:
- Greps
01-spec.mdfor**AC-NNN**headers → AC list. - Greps
04-tasks.mdfor task entries with**AC-IDs:**→ AC↔task mapping. - Scans
src/test/java/**/*.javafor@Tag("AC-NNN")and@DisplayName("AC-NNN: …")→ AC↔test mapping. - Reads
git diff --name-only origin/main...HEAD→ changed files; intersects with JaCoCo's per-method coverage data → covered/uncovered symbols. - Reads
harness-summary.json→ gates that ran. - Emits
07a-traceability.md.
Required checks (all must pass)
- No uncovered AC. Every
AC-NNNappears in ≥1 test's@Tagor@DisplayName. - No orphan test. Every test method tagged
AC-NNNreferences a real AC. - No orphan code. Every changed production method has ≥1 covering test.
- No untraced task. Every
T-NNNmarkeddonein04-tasks.mdhas a commit recorded.
Failures of any check → validator returns ❌.
Sample output (truncated)
## Coverage
| AC-ID | Tasks | Tests | Status |
|-------|-------|-------|--------|
| AC-001 | T-001, T-002 | ApplyGiftCardRequestTest#rejectsBlankCode, CheckoutControllerTest#happyPath | ✅ |
| AC-002 | T-003 | CheckoutServiceTest#redeemedCardRejected, CheckoutControllerIT#redeemed409 | ✅ |
| AC-003 | T-002 | CheckoutControllerTest#unknownCode404 | ✅ |
| AC-004 | T-004 | GiftCardRepositoryIT#balanceAcrossOrders | ✅ |
## Orphan tests
_None._
## Orphan code
_None._
## Verdict
✅ All ACs covered. No orphans.
Tagging convention (enforced)
@Test
@DisplayName("AC-007: rejects expired gift card with 4xx")
@Tag("AC-007")
void rejectsExpired() { ... }
Both @DisplayName and @Tag are written for redundancy — one is human-friendly, the other machine-friendly.
A Checkstyle rule rejects test methods that have @DisplayName matching ^AC-\\d{3}: without a matching @Tag.
Anti-patterns
- One mega-test that asserts five ACs at once → split.
- Tests that only tag the highest-numbered AC of a related group → tag every AC asserted.
- "Tag and forget" — agent tags the test but the assertion doesn't actually exercise the AC.
- Removing a tag to make traceability green.