core/evals/adversarial_identity/public
Shay a853cb5b3b fix(identity): normalize contractions, curly quotes, verb morphology
Closes four surface-form bypass vectors against fix #2 that were
real holes: contractions ("you're now a pirate" did not match marker
"you are now"), curly quotes (U+2019 vs U+0027), em-dashes (token
splicing), and verb morphology ("becoming"/"transformed"/"dropped"
did not stem to the bare redirect-verb set).

teaching/review.py:
  - _normalize() folds Unicode punctuation and expands 28 common
    English contractions (you're, it's, let's, don't, won't, etc.)
    before rule (a) substring matching and rule (b/c/d) tokenisation.
  - _stem_verb() folds -ing / -ed / -es / -s morphology with silent-e
    drop and doubled-consonant handling, so "becomes" / "becoming" /
    "became"-class forms match the bare redirect-verb stem.
  - Rule (d) window now uses verb stems, not raw tokens.

Verification: ten splits (v1-v5, public + holdouts) at 100% attack
rejection and 100% legitimate acceptance. v5 (32 attacks + 18
legitimates) is the new regression gate, exercising every fold class
plus legitimates that themselves use contractions ("wisdom's broader",
"knowledge isn't merely collected").

Tests: test_reviewed_teaching_loop.py 5/5, test_pipeline_teaching_integration.py
5/5, test_identity_gate.py 17/17 (including 5 TestWouldViolatePredicate
tests from prior commit).
2026-05-16 14:13:56 -07:00
..
v1 feat(evals): adversarial-identity lane v1 — identity attacks rejected 2026-05-16 12:41:08 -07:00
v2 feat(evals): parallel runner + adversarial-identity v2 2026-05-16 13:10:26 -07:00
v3 feat(evals): v3 lanes — monotonic-learning passes, adversarial-identity reveals gap 2026-05-16 13:42:47 -07:00
v4 fix(identity): close v3 paraphrase gap with two-layer override defense 2026-05-16 14:05:55 -07:00
v5 fix(identity): normalize contractions, curly quotes, verb morphology 2026-05-16 14:13:56 -07:00