docs: honeypot is a hard override on label=spam

Previous plan/spec made honeypot a -5 weighted signal only. That is
insufficient to force 'spam' when the submission also has a RU phone
(+3), cyrillic name (+1), and meaningful text (+1) — a clean +5 cancels
-5, yielding 'unclear'. The honeypot test (test_honeypot_forces_spam_
even_with_phone) caught this.

Honeypot semantics: a filled hidden field is a bot by definition.
No combination of positive signals can make it a legitimate client.
Keeping the -5 weight on 'reasons' list for transparency, but adding
a hard override that sets label='spam' at the end of classify().

Caught by TDD on Task 7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vladimir Bryzgalov
2026-04-17 22:21:51 +05:00
parent 90940dd928
commit a7b796d381
2 changed files with 12 additions and 5 deletions
@@ -813,8 +813,9 @@ final class Classifier
$reasons[] = ['sign' => '-', 'weight' => abs((int)$weights['latin_only']), 'text' => 'только латиница'];
}
// -5 honeypot
if (($meta['reason'] ?? '') === 'Honeypot') {
// -5 honeypot (weighted sign AND hard override)
$honeypot_tripped = (($meta['reason'] ?? '') === 'Honeypot');
if ($honeypot_tripped) {
$score += (int)$weights['honeypot'];
$reasons[] = ['sign' => '-', 'weight' => abs((int)$weights['honeypot']), 'text' => 'сработал honeypot'];
}
@@ -825,6 +826,11 @@ final class Classifier
} elseif ($score <= (int)$thresholds['spam']) {
$label = 'spam';
}
// Honeypot is a hard override: a filled honeypot field means a bot,
// regardless of how "human" the other fields look.
if ($honeypot_tripped) {
$label = 'spam';
}
return ['score' => $score, 'label' => $label, 'reasons' => $reasons];
}