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 addedC_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 = simplerKey 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 / LOCinstead 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 constantAny .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.