Builds a bidirectional traceability matrix linking requirements to design elements, code, and tests — so every requirement traces forward to its implementation and every test traces back to its justification. Use for compliance audits, when answering why a piece of code exists, or when checking that nothing was built without a reason.
80
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Traceability answers two questions: "What implements this requirement?" (forward) and "Why does this code exist?" (backward). The matrix is the answer in table form.
Requirement ──► Design element ──► Code ──► Test
▲ │
└─────────────────────────────────────────┘
(test verifies req)Every link is a traceable edge. Gaps are rows with empty cells.
| Req ID | Requirement (brief) | Design | Code | Test | Status |
|---|---|---|---|---|---|
| REQ-1.1 | Rate limit: 100/min/user | RateLimiter component | middleware/ratelimit.py | test_ratelimit_100_per_min | ✓ |
| REQ-1.2 | Return 429 on limit | — | ratelimit.py:L45 | test_ratelimit_returns_429 | ✓ |
| REQ-2.1 | Audit all writes | AuditLogger | audit.py | — | ⚠ No test |
| REQ-3.4 | Support IPv6 | — | — | — | ❌ Gap |
requirement-coverage-checker techniques: grep for IDs, grep for domain terms, structural search.pytest --cov) tell you which tests hit which lines.Forward trace finds unimplemented requirements. Backward trace finds unrequired code:
| Trace type | Strength | Maintenance cost |
|---|---|---|
| Explicit ID in code/test | Strong | Low — grep finds it |
@covers("REQ-1.1") decorator | Strong | Low — machine-checkable |
| Mention in docstring | Medium | Medium — can drift |
| Structural match (inferred) | Weak | High — re-derive every audit |
For auditable systems: use explicit IDs. # REQ-1.1 in the code, @pytest.mark.req("1.1") on the test. Then the matrix is a grep, not an archaeology dig.
Convention in this codebase: tests carry @pytest.mark.req("X.Y"); code has # REQ-X.Y comments.
# middleware/ratelimit.py
# REQ-1.1, REQ-1.2
@app.middleware("http")
async def ratelimit(request, call_next):
...
# tests/test_ratelimit.py
@pytest.mark.req("1.1")
def test_ratelimit_allows_100_per_minute(): ...
@pytest.mark.req("1.2")
def test_ratelimit_returns_429_on_excess(): ...Matrix generation (scripted):
import re, ast, pathlib
reqs = load_requirements("spec.md") # {id: text}
code_traces = {} # {req_id: [file:line, ...]}
test_traces = {} # {req_id: [test_name, ...]}
for f in pathlib.Path("src").rglob("*.py"):
for lineno, line in enumerate(f.read_text().splitlines(), 1):
for rid in re.findall(r"REQ-(\d+\.\d+)", line):
code_traces.setdefault(rid, []).append(f"{f}:{lineno}")
for f in pathlib.Path("tests").rglob("*.py"):
tree = ast.parse(f.read_text())
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
for dec in node.decorator_list:
# match @pytest.mark.req("X.Y")
if (isinstance(dec, ast.Call) and ast.unparse(dec.func) == "pytest.mark.req"):
rid = dec.args[0].value
test_traces.setdefault(rid, []).append(f"{f.name}::{node.name}")
# Emit matrix
for rid, text in reqs.items():
code = code_traces.get(rid, [])
tests = test_traces.get(rid, [])
status = "✓" if code and tests else ("⚠" if code else "❌")
print(f"| {rid} | {text[:40]} | {', '.join(code) or '—'} | {', '.join(tests) or '—'} | {status} |")Mechanical, reproducible, runs in CI.
auth.py implements 30 requirements — that's not a trace, that's a guess. Trace to functions or regions.## Matrix
| Req ID | Requirement | Design | Code | Test | Status |
| ------ | ----------- | ------ | ---- | ---- | ------ |
## Gaps (forward — unimplemented)
| Req ID | Missing | Action |
| ------ | ------- | ------ |
## Orphans (backward — unjustified code)
| Code | Classification | Action |
| ---- | -------------- | ------ |
| <func> | Implicit infra | None — expected |
| <func> | Undocumented req | Add REQ-X.Y to spec |
| <func> | Speculative | Consider removal |
## Trace strength
Explicit (tagged): <N> Inferred: <M> — lower M by tagging
## Regeneration
<command to rebuild this matrix — goes in CI>47d56bb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.