AFAdocs
Gates

Complexity Gate

The only non-overridable gate -- complexity hard floor at 0.5.

Complexity Gate

The complexity gate is the only gate with a hard floor. If the normalized complexity score is below 0.5, the enhancement is rejected immediately. No configuration, override, or retry can bypass this.

Why it exists

The complexity hard floor prevents AFA from making changes that add too much structural complexity, even if every other gate passes. An enhancement that improves security but doubles cyclomatic complexity is not worth it -- the maintenance burden will exceed the security benefit over time.

The score

C_norm is a normalized complexity score where higher means simpler (counterintuitive, but preserved for compatibility with the AEGIS GateEvaluator).

  • C_norm = 1.0 -- no complexity added
  • C_norm = 0.5 -- at the threshold (barely passes)
  • C_norm = 0.0 -- extremely complex change (rejected)

V2 formula

Calibrated 2026-03-14 after SCARAB lambda testing (V1 was too aggressive: 0/15 pass -> V2: 10/15 pass).

structural_density = structural_additions / max(original_loc, 15)
token_ratio = min(1.0, max(0, tokens_added) / max(tokens_target, 1))

base = (
    0.4 * (max(0, delta_loc) / 1000) +   # Asymmetric: deletions are free
    0.3 * structural_density +             # Density, not raw count
    0.15 * token_ratio                     # Capped at 1.0
)

C_norm = max(0.0, 1.0 - max(0.05, base))  # Invert: higher = simpler

Key design decisions

  • Deletions are free: max(0, delta_loc) means removing lines never hurts the complexity score. Refactoring that reduces LOC always passes the complexity gate more easily.
  • Density-based structural cost: uses structural_additions / LOC instead of raw structural count. A 5-line function adding 2 control structures is more complex than a 500-line function adding 2.
  • Capped token ratio: min(1.0, ...) prevents token count from dominating the score.
  • Minimum base of 0.05: even trivial changes get a small complexity cost, preventing the score from being exactly 1.0.

Troubleshooting

"complexity_score < 0.5" on small functions

Small functions (< 15 LOC) inflate structural_density because the denominator is clamped to max(original_loc, 15). If your original function is 5 lines, adding 3 structural elements gives density of 3/15 = 0.2 instead of 3/5 = 0.6. The floor at 15 is intentional -- it prevents tiny functions from being impossible to enhance.

"complexity_score < 0.5" on large additions

If your enhancement adds significant LOC, the 0.4 * (delta_loc / 1000) term drives up the base. An enhancement adding 200 lines contributes 0.4 * 0.2 = 0.08 to base -- usually fine. But 500+ lines of additions will approach the threshold.

Configuration

The complexity floor cannot be changed:

gates:
  complexity_floor: 0.5  # This value is enforced as a constant

Any .afa.yaml that sets complexity_floor to a value other than 0.5 will fail at load time with a ConfigError. This is enforced by a Pydantic validator using a const constraint in the schema.

On this page