Sponsored by

SnackOnAI Engineering | Senior AI Systems Researcher | Technical Deep Dive | May 23, 2026

Requirements traceability, the ability to link every piece of code to the requirement it implements and every requirement to the code that implements it, is a mandatory artifact in safety-critical systems: aerospace, medical devices, automotive, financial systems with regulatory obligations. The standard in these domains is bidirectional traceability: forward (requirement → code) and backward (code → requirement). When a requirement changes, you know which code to modify. When a code module is removed, you know which requirement it was serving.

The problem LLMs introduced to this workflow is subtle: they generate functionally correct code while producing trace links that are imprecise, incomplete, or missing entirely. A model that generates a 500-line class satisfying three different requirements may produce code where it is unclear which methods implement which requirements, where some requirements have no implementing code, and where some methods implement requirements not in the specification. The code compiles. The tests pass. The traceability matrix is a mess.

R2Code (arXiv:2604.22432, April 2026) is a self-reflective LLM framework for requirements-to-code traceability. It takes requirements as input and produces both code and trace links simultaneously, then applies a reflection loop to verify and improve trace link quality before finalizing output. The framework operates in three phases: requirements parsing, code generation with embedded trace annotations, and a self-reflective verification loop that identifies missing, spurious, and incorrect trace links and regenerates the affected code sections.

This newsletter dissects R2Code as a systems engineering document: how requirements are parsed and represented, what the trace-annotated code generation format looks like, how the self-reflection loop is structured and why it converges, and what the benchmark results on standard traceability datasets (iTrust, EasyClinic, CoCoTrace) reveal about where the framework succeeds and where it fails.

Scope: R2Code architecture (arXiv:2604.22432), the three-phase pipeline, the self-reflection mechanism, and the benchmark evaluation. Not covered: the broader requirements management toolchain integration beyond the R2Code interface, or formal verification methods beyond automated testing.

What It Actually Does

R2Code takes a requirements specification as input (natural language or structured requirements document) and produces two artifacts: (1) code implementing all requirements, with inline trace annotations mapping each code unit to its source requirement, and (2) a traceability matrix documenting the complete requirement-to-code and code-to-requirement mapping.

The framework's distinguishing mechanism is the self-reflection loop: after initial code generation, the system uses the LLM itself to verify the trace links, identify gaps and errors, and regenerate only the sections where traceability is broken. This iterative process continues until the traceability matrix is complete or a maximum iteration count is reached.

Why this is different from standard code generation:

Standard code generation: requirements in → code out (trace links implicit or absent) R2Code: requirements in → (code + trace links) out, iteratively verified for completeness

Standard traceability benchmarks:

Dataset

Domain

Requirements

Code Units

Standard Use

iTrust

Healthcare web app

34 use case requirements

167 Java classes/methods

Trace link precision/recall

EasyClinic

Hospital management

42 requirements

80 Java classes

Bidirectional traceability

CoCoTrace

Telecom system

127 high-level requirements

412 functions

Large-scale F1 evaluation

The Architecture, Unpacked

Focus on the selective regeneration in Phase 3. The framework does not regenerate all code when a trace link fails verification. It regenerates only the specific code unit where the link is broken, using the failure context as additional input. This preserves correct code from previous iterations and reduces token cost per iteration.

The Code, Annotated

Snippet One: Trace-Annotated Code Generation and Reflection Loop

# R2Code framework (reconstructed from arXiv:2604.22432 architecture description)
# The key innovation is generating code and trace links simultaneously,
# then using the LLM to verify its own trace links

import json
from dataclasses import dataclass, field
from typing import Optional

@dataclass
class Requirement:
    id: str         # "REQ-001"
    text: str       # full requirement text
    priority: str   # "shall" (mandatory) | "should" (preferred) | "may" (optional)

@dataclass
class TraceLink:
    requirement_id: str    # "REQ-001"
    code_unit: str         # "AuthenticationService.authenticate"
    confidence: float      # 0.0-1.0, from reflection verification
    verified: bool = False

@dataclass
class CodeUnit:
    name: str
    code: str
    trace_links: list[str]  # list of requirement IDs this unit satisfies

# Phase 1: Parse requirements into structured representation
def parse_requirements(spec_text: str, llm) -> list[Requirement]:
    """
    LLM extracts structured requirements from natural language spec.
    Assigns IDs, identifies priority (shall/should/may), extracts entities.
    ← Why structured output? Downstream coverage checking needs to enumerate
      requirements as discrete items. Free-text doesn't support this.
    """
    prompt = f"""
    Parse the following requirements specification into structured requirements.
    For each requirement, extract:
    - id: unique identifier (REQ-001, REQ-002, etc.)
    - text: verbatim requirement text
    - priority: "shall" | "should" | "may"

    Requirements specification:
    {spec_text}

    Return JSON: [{{"id": str, "text": str, "priority": str}}]
    """
    response = llm.generate(prompt, format="json")
    return [Requirement(**r) for r in json.loads(response)]

# Phase 2: Generate code with embedded trace annotations
def generate_traced_code(requirements: list[Requirement], llm) -> list[CodeUnit]:
    """
    Generate implementation code where each code unit is annotated
    with the requirements it satisfies.

    ← THIS is the key design decision: trace links are NOT inferred after
      code generation. They are generated SIMULTANEOUSLY with the code.
      This means the model is explicitly asked to reason about traceability
      during code generation, not as an afterthought.

    The @satisfies annotation format is chosen for:
    - Parsability: easily extracted by regex or AST parser
    - Visibility: reviewers can see trace links directly in code
    - Maintainability: trace links co-locate with the code they describe
    """
    req_list = "\n".join([f"{r.id}: {r.text}" for r in requirements])

    prompt = f"""
    Implement all of the following requirements in Python.
    For each class and method, add a @satisfies annotation listing which
    requirements it implements. A single method may satisfy multiple requirements.
    A requirement may be satisfied by multiple methods.

    Requirements:
    {req_list}

    Format for annotations:
    # @satisfies: REQ-001, REQ-003  (for class-level)
    # @satisfies: REQ-001           (for method-level)

    Generate complete, runnable Python code with all annotations.
    """
    raw_code = llm.generate(prompt)
    return parse_code_units(raw_code)  # extract CodeUnits from generated code

# Phase 3: Self-reflection verification loop
def reflect_and_verify(
    requirements: list[Requirement],
    code_units: list[CodeUnit],
    llm,
    max_iterations: int = 3,
) -> tuple[list[CodeUnit], list[TraceLink]]:
    """
    The self-reflection loop: verify trace links and regenerate as needed.

    Three verification passes per iteration:
    1. Coverage: every requirement has at least one satisfying code unit
    2. Spurious links: every asserted trace link is actually correct
    3. Missing links: code units that should satisfy a requirement but don't

    ← Why use the LLM for verification? Static analysis can check syntax.
      Only the LLM can check semantic correctness: "does this code actually
      implement this requirement?"

    ← Why iterate? Initial generation may produce incomplete trace annotations.
      The reflection loop is the error-correction mechanism.
    """
    trace_links = extract_trace_links(code_units)
    req_map = {r.id: r for r in requirements}

    for iteration in range(max_iterations):
        issues_found = []

        # Check 1: Coverage (every requirement has implementing code)
        covered_reqs = {link.requirement_id for link in trace_links}
        missing_coverage = [r for r in requirements if r.id not in covered_reqs]

        for req in missing_coverage:
            issues_found.append({
                "type": "missing_coverage",
                "requirement": req,
                "message": f"No code unit satisfies {req.id}: {req.text}"
            })

        # Check 2: Spurious link verification
        for link in trace_links:
            req = req_map.get(link.requirement_id)
            code_unit = get_code_unit(code_units, link.code_unit)
            if req and code_unit:
                # ← LLM verifies semantic alignment between requirement and code
                # This is the core of self-reflection: the model critiques its own output
                verification_prompt = f"""
                Does this code unit satisfy the stated requirement?

                Requirement {req.id}: {req.text}

                Code unit ({code_unit.name}):
                {code_unit.code}

                Answer: YES or NO, then explain in one sentence.
                """
                verdict = llm.generate(verification_prompt)
                if "NO" in verdict.upper():
                    issues_found.append({
                        "type": "spurious_link",
                        "link": link,
                        "reason": verdict,
                    })
                    link.confidence = 0.0
                else:
                    link.confidence = 1.0
                    link.verified = True

        if not issues_found:
            break  # ← Early termination: all links verified

        # Selective regeneration: only fix broken code units
        # ← THIS is the trick: don't regenerate everything, only what's broken
        # This preserves correct code and reduces token cost per iteration
        code_units = selective_regenerate(
            code_units, issues_found, requirements, llm
        )
        trace_links = extract_trace_links(code_units)

    return code_units, trace_links

The semantic verification step (does this code actually implement this requirement?) is where self-reflection does work that static analysis cannot. A requirements coverage tool can check that every requirement ID appears in at least one annotation. Only the LLM can check that the annotated code actually implements the requirement semantically, not just syntactically.

Snippet Two: Traceability Matrix Generation and Evaluation

# Traceability matrix output and evaluation metrics
# This is what R2Code produces and how it is measured

import json
from collections import defaultdict

def build_traceability_matrix(
    requirements: list[Requirement],
    trace_links: list[TraceLink],
    code_units: list[CodeUnit],
) -> dict:
    """
    Build bidirectional traceability matrix from verified trace links.

    Bidirectional traceability:
    - Forward: requirement → {code units that implement it}
    - Backward: code unit → {requirements it implements}

    ← Why bidirectional? Both directions are needed in practice:
      Forward: when requirement changes, find all code to update
      Backward: when reviewing code, verify it has a traced requirement (no orphan code)
    """
    forward_trace = defaultdict(list)  # req_id → [code_units]
    backward_trace = defaultdict(list) # code_unit → [req_ids]

    for link in trace_links:
        if link.verified or link.confidence > 0.5:
            forward_trace[link.requirement_id].append(link.code_unit)
            backward_trace[link.code_unit].append(link.requirement_id)

    # Identify coverage gaps
    gaps = [r for r in requirements if r.id not in forward_trace]
    orphans = [cu for cu in code_units if cu.name not in backward_trace]

    return {
        "forward": dict(forward_trace),
        "backward": dict(backward_trace),
        "coverage": {
            "total_requirements": len(requirements),
            "covered": len(forward_trace),
            "gaps": [(r.id, r.text[:60]) for r in gaps],  # uncovered requirements
            "orphans": [cu.name for cu in orphans],        # code with no requirement
        }
    }

def evaluate_traceability(
    predicted_matrix: dict,
    ground_truth_matrix: dict,
    metric: str = "f1",
) -> dict:
    """
    Standard evaluation metrics for requirements traceability.

    Precision: of all predicted trace links, what fraction are correct?
    Recall: of all true trace links, what fraction were predicted?
    F1: harmonic mean of precision and recall
    F2: recall-weighted F1 (used in safety-critical contexts where missing
        a trace link is more costly than a spurious one)

    ← F2 is often preferred in traceability because missing a link
      (failing to trace code to a requirement) is more dangerous than
      a false link (incorrectly claiming code satisfies a requirement).
      In safety-critical systems, the former can mean unverified compliance.
    """
    predicted_links = set()
    for req_id, code_units in predicted_matrix["forward"].items():
        for cu in code_units:
            predicted_links.add((req_id, cu))

    ground_truth_links = set()
    for req_id, code_units in ground_truth_matrix["forward"].items():
        for cu in code_units:
            ground_truth_links.add((req_id, cu))

    true_positives = len(predicted_links & ground_truth_links)
    false_positives = len(predicted_links - ground_truth_links)
    false_negatives = len(ground_truth_links - predicted_links)

    precision = true_positives / (true_positives + false_positives + 1e-9)
    recall = true_positives / (true_positives + false_negatives + 1e-9)
    f1 = 2 * precision * recall / (precision + recall + 1e-9)
    # ← F2: weights recall twice as much as precision
    f2 = (1 + 4) * precision * recall / (4 * precision + recall + 1e-9)

    return {"precision": precision, "recall": recall, "f1": f1, "f2": f2}

# R2Code benchmark results (from arXiv:2604.22432):
# Dataset         Precision    Recall    F1      F2
# iTrust          0.84         0.79      0.81    0.80
# EasyClinic      0.81         0.82      0.81    0.81
# CoCoTrace       0.76         0.75      0.75    0.75
#
# Prior SOTA (TraceLLM, arXiv:2602.01253, on same datasets):
# Achieved strong F2 scores on aerospace/healthcare datasets
# but was evaluated on different artifact types (requirements → design)

The F2 metric weighting recall over precision is the correct evaluation choice for safety-critical traceability. A missed trace link (a requirement that has no code mapped to it) is a compliance gap that may go undetected until audit time. A spurious trace link (code incorrectly annotated as satisfying a requirement) will likely be caught during code review. Weighting recall higher reflects this asymmetry.

It In Action: End-to-End Worked Example

Input: Authentication module requirements for a healthcare web application (based on iTrust benchmark domain)

Requirements specification:

REQ-001: The system shall authenticate users via valid email and password combination.
REQ-002: Authentication sessions shall expire after 15 minutes of inactivity.
REQ-003: Failed login attempts shall be logged with timestamp, user email, and IP address.
REQ-004: After 5 consecutive failed login attempts, the account shall be locked.
REQ-005: Password reset shall require verification via email link valid for 60 minutes.

Phase 1 output (structured requirements):

[
  {"id": "REQ-001", "text": "...", "priority": "shall", "entities": ["user", "email", "password"]},
  {"id": "REQ-002", "text": "...", "priority": "shall", "entities": ["session", "timeout", "15min"]},
  {"id": "REQ-003", "text": "...", "priority": "shall", "entities": ["log", "timestamp", "email", "IP"]},
  {"id": "REQ-004", "text": "...", "priority": "shall", "entities": ["lockout", "5 attempts"]},
  {"id": "REQ-005", "text": "...", "priority": "shall", "entities": ["password_reset", "email", "60min"]}
]
Dependency graph: REQ-003 depends on REQ-001; REQ-004 depends on REQ-003

Phase 2 output (excerpt, trace-annotated code):

# @satisfies: REQ-001, REQ-004
class AuthenticationService:
    # @satisfies: REQ-001
    def authenticate(self, email: str, password: str) -> AuthResult:
        ...

    # @satisfies: REQ-002
    def check_session_timeout(self, session_id: str) -> bool:
        ...

    # @satisfies: REQ-003
    def log_failed_attempt(self, email: str, ip_address: str) -> None:
        ...

    # @satisfies: REQ-004
    def enforce_lockout_policy(self, email: str) -> None:
        ...

    # @satisfies: REQ-005
    def initiate_password_reset(self, email: str) -> str:
        ...

Initial trace matrix:

REQ-001: [authenticate]
REQ-002: [check_session_timeout]
REQ-003: [log_failed_attempt]
REQ-004: [enforce_lockout_policy]  ← also listed at class level but not REQ-001 class annotation
REQ-005: [initiate_password_reset]

Phase 3 iteration 1 (self-reflection):

Coverage check:
  All 5 requirements covered ✓

Spurious link check:
  (REQ-001, AuthenticationService class) → verify: "Does the class implement auth?"
  LLM verdict: YES ✓
  (REQ-004, enforce_lockout_policy) → verify: "Does this implement 5-attempt lockout?"
  LLM inspects code: missing the count-and-compare logic
  Verdict: NO — code calls lockout but doesn't count attempts
  → Issue: spurious link at method level

  (REQ-004, authenticate) → not annotated but LLM detects: authenticate calls
  enforce_lockout_policy which is REQ-004, but authenticate itself should
  also be annotated as satisfying REQ-004 (it's where the attempt is counted)
  → Issue: missing link

Selective regeneration:
  Regenerate: enforce_lockout_policy (add attempt counting logic)
  Add missing annotation: authenticate @satisfies: REQ-001, REQ-004

Phase 3 iteration 2:

Coverage check: ✓ (all 5 requirements)
Spurious link check: all links verified ✓
No further issues found.
Terminate at iteration 2.

Final trace matrix:
  REQ-001: [authenticate, AuthenticationService]
  REQ-002: [check_session_timeout]
  REQ-003: [log_failed_attempt]
  REQ-004: [enforce_lockout_policy, authenticate]
  REQ-005: [initiate_password_reset]

Traceability coverage:
  5/5 requirements covered (100%)
  0 orphan code units
  0 uncovered requirements

Token usage:
  Phase 1 (parsing):         ~600 tokens
  Phase 2 (generation):     ~3,200 tokens
  Phase 3 iter 1:           ~2,100 tokens (verification of 5 links + 2 regenerations)
  Phase 3 iter 2:           ~1,400 tokens (verification only)
  Total:                    ~7,300 tokens

vs. baseline (generate code, then separately recover trace links):
  Code generation:           ~3,200 tokens
  Trace recovery (separate): ~4,500 tokens (for all pairwise comparisons)
  Total:                     ~7,700 tokens
  ← R2Code is slightly cheaper AND produces better trace links
     because simultaneous generation avoids the pairwise comparison explosion

Why This Design Works, and What It Trades Away

Simultaneous generation of code and trace links, rather than first generating code and then recovering trace links, is the architectural decision that makes R2Code more efficient than prior approaches at scale. The alternative (retrospective trace link recovery) requires comparing every requirement against every code unit: O(R × C) comparisons where R is requirements count and C is code unit count. For a system with 100 requirements and 500 code units, that is 50,000 pairwise comparisons. R2Code's simultaneous generation collapses this to a single generation pass plus a targeted verification loop.

The self-reflection mechanism is the correct error-correction approach for this domain. Static analysis can verify that @satisfies annotations are syntactically present. Only the LLM can verify that the annotated code semantically implements the stated requirement. The LLM's ability to read both a natural language requirement and a code implementation and assess their alignment is the capability that makes verification tractable without human review of every trace link.

The selective regeneration in the reflection loop is the design decision that controls cost. A naive implementation would regenerate all code on any verification failure. R2Code regenerates only the code units where specific trace links failed verification. For a system where 90% of trace links are correct after initial generation, this reduces iteration cost by 90%.

What R2Code trades away:

Verification accuracy bounds. The self-reflection mechanism uses the LLM to verify its own output. If the LLM systematically misunderstands how a particular type of requirement maps to code, it will both generate incorrect trace links and verify them as correct. The verification loop catches random errors but not systematic biases in the model's understanding of the requirement domain.

Determinism. Like all LLM-based code generation, R2Code produces different outputs on different runs. The trace matrix will vary between runs for the same requirements specification. For certification purposes (where traceability must be auditable), the non-determinism requires additional process controls.

Maximum iterations as a convergence proxy. The iteration limit (typically 2-3) is set empirically. There is no formal convergence guarantee: a pathological requirement/code combination could oscillate without converging to a verified trace link. The empirical finding that 2-3 iterations is sufficient for standard benchmarks does not guarantee this for novel domain-specific requirements.

Technical Moats

The bidirectional verification: forward and backward simultaneously. Prior traceability approaches recover links in one direction (requirement → code or code → requirement) and infer the other. R2Code's simultaneous generation produces bidirectional trace links from the start, allowing the verification loop to catch issues in both directions. Implementing correct bidirectional verification requires careful attention to the asymmetric cost of false positives vs false negatives (which is why F2 is the primary metric), and this design decision has to be made deliberately rather than falling out of the architecture naturally.

Domain-specific reflection prompts. The quality of the self-reflection loop depends heavily on how the verification prompt is constructed. Generic prompts ("is this code correct?") produce lower-quality verification than domain-specific prompts that reference the requirement's specific entities, constraints, and priorities. Tuning the reflection prompt for specific requirement domains (safety-critical vs. web application vs. embedded systems) is the practical moat that separates a deployed R2Code system from an academic implementation.

The @satisfies annotation format as a standard. If the @satisfies annotation format becomes a de facto standard for LLM-generated code in regulated industries, the framework that established the format has a significant adoption advantage. Similar to how JavaDoc established comment conventions for Java, a trace annotation standard could create tool ecosystem effects that compound over time.

Insights

Insight One: Requirements traceability is the domain where "just generate the code" fails most visibly and most expensively. R2Code's value proposition is not that it generates better code than a direct prompt. It is that it generates code that can be audited, certified, and maintained in regulated environments.

A startup building a web app does not need requirements traceability. A medical device manufacturer building a patient dosing system has legal obligations under FDA 21 CFR Part 11 and ISO 62304 to maintain bidirectional traceability between requirements and code. An automotive supplier building safety-critical software operates under ISO 26262. In these environments, code that cannot be traced to requirements cannot be certified, and code that cannot be certified cannot ship. The market for automated traceability is not the general developer productivity market. It is the regulated software development market, which is measured in tens of billions of dollars and has almost no automation today.

Insight Two: The self-reflection loop's most important contribution is not improving precision or recall on existing benchmarks. It is enabling iterative development of requirements and code simultaneously, which is how requirements engineering actually works in practice.

Requirements documents are not written once and then implemented. They are iteratively refined as implementation reveals ambiguities, conflicts, and missing details. R2Code's architecture, where requirements and code are generated together and the reflection loop maintains trace consistency, supports this iterative workflow: add a new requirement, run R2Code, get updated code and trace matrix, identify conflicts, refine requirements, repeat. The academic benchmark evaluation (static requirements → static code → measure F1) captures only a fraction of the workflow value. The iterative requirements development use case is the more practically important one.

Surprising Takeaway

The simultaneous generation of code and trace links is not just a performance optimization. It fundamentally changes what the LLM is being asked to do, and the change produces better trace links than post-hoc recovery on the same code.

When the LLM generates code and trace annotations simultaneously, it is planning the implementation around requirements: "I am implementing REQ-001, so this authenticate() method satisfies REQ-001." The trace links are a byproduct of the implementation plan. When trace links are recovered after code generation, the LLM is asked a different question: "given this code that already exists, which requirements does it satisfy?" This is a harder semantic judgment because the code's structure may not align naturally with the requirements structure, and the LLM must work backward from implementation to intent. The simultaneous generation produces trace links that are better not because the model is smarter but because the task framing is more natural to how requirements-to-code implementation actually proceeds.

TL;DR For Engineers

  • R2Code (arXiv:2604.22432, April 2026) is a three-phase framework: requirements parsing (structured representation + dependency graph), trace-annotated code generation (simultaneous @satisfies annotations), and a self-reflective verification loop (coverage, spurious link, and consistency checks with selective regeneration). Terminates in 2-3 iterations on standard benchmarks.

  • Simultaneous code and trace link generation is more efficient than retrospective trace recovery: avoids the O(R × C) pairwise comparison explosion. For 100 requirements and 500 code units, R2Code avoids 50,000 pairwise comparisons.

  • Self-reflection uses the LLM to verify semantic alignment between requirements and code, catching both spurious links (code annotated for wrong requirement) and missing links (code that should be annotated but isn't). Static analysis cannot do this.

  • Bidirectional traceability matrix output: forward (requirement → code units) and backward (code unit → requirements). Identifies both coverage gaps (uncovered requirements) and orphan code (code with no traced requirement).

  • Primary market: regulated software development (medical devices, automotive safety, aerospace) where traceability to requirements is a legal and certification obligation, not a nice-to-have.

The Audit Trail Is Now Part of the Code

R2Code's most important design decision is the simplest one: put the trace links in the code, not in a separate document. The @satisfies annotation co-locates the traceability artifact with the implementation it describes. When the code changes, the annotation is visible in the same diff. When the code is reviewed, the trace link is readable without opening a separate requirements management tool. When the code is compiled, static analysis can verify that every annotation references a valid requirement ID.

Traceability has always been a documentation problem masquerading as a technical problem. R2Code makes it a code problem.

References

R2Code (arXiv:2604.22432, April 2026) is a self-reflective LLM framework for requirements-to-code traceability that generates code and trace links simultaneously, then applies an iterative verification loop (coverage check, spurious link detection, consistency verification) with selective regeneration to correct traceability errors. The simultaneous generation avoids the O(R × C) pairwise comparison cost of retrospective trace recovery and produces bidirectional traceability matrices (forward: requirement → code units, backward: code unit → requirements) within 2-3 reflection iterations. The primary target is regulated software development domains (medical devices, automotive, aerospace) where bidirectional traceability is a legal obligation under standards including ISO 62304, ISO 26262, and FDA 21 CFR Part 11.

Sponsored Ad

If you enjoy practical AI insights, check out SnackOnAI and support the newsletter by subscribing, sharing, and exploring our sponsored ad — it helps us keep building and delivering value 🚀

Catch Bad Actors. Let Good Users Flow.

Online traffic isn’t just “human vs bot” anymore.

It’s AI agents, good bots, bad bots… all blending in and getting harder to detect.

That’s where hCaptcha stands out.

Traditional security methods are falling behind. hCaptcha exposes hidden threats with adaptive AI models and intent analysis, providing instant, private verification. 

Don’t just take it from us, hear from one of our customers: 

“Compared to last year [when using competitor], we had a 96% reduction in bot throughput.” - Top 10 Gaming Company 

Virtually all companies that book a demo with hCaptcha decide to move forward.

Recommended for you