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.
Install with Tessl CLI
npx tessl i github:santosomar/general-secure-coding-agent-skills --skill traceability-matrix-generator100
Quality
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.