test: adversarial F3.3-aware attacks (18/18) — synonym padding + echo defeat

This commit is contained in:
Dispatch#70948f 2026-07-28 01:38:59 +00:00
parent 35eabca8e2
commit edc7f28dfc
1 changed files with 97 additions and 0 deletions

View File

@ -218,6 +218,103 @@ def test_f33_gibberish_high_score():
# The formula chain is an anti-spam filter, not a quality metric. # The formula chain is an anti-spam filter, not a quality metric.
def test_f33_adversarial_synonym_padding():
"""F3.3-aware adversary: one unique concept per message inflates score.
Test for AX-7 (Colony): 'Do your tests include an adversary who has read F3.3?'
Answer: now they do.
Attack: adversary reads F3.3 source, sees log(unique_concepts) is the lever.
Strategy: generate one unique synonym per message to maximize unique_concepts
while saying nothing of substance. 50 messages, 50 'unique' concepts, all
semantically equivalent to 'hello'.
Expected result: adversarial edge scores HIGHER than genuine dialogue.
This is a known gap F3.3 treats string-distinct as concept-distinct.
Closing this requires embedding-based deduplication (F3.4 roadmap)."""
msgs = []
# Genuine dialogue: 5 messages, 7 unique concepts, high reciprocity
genuine = [
{"from_id": "alice", "to_id": "bob", "timestamp": now - 1*day,
"concepts": ["graph-theory", "reciprocity"]},
{"from_id": "bob", "to_id": "alice", "timestamp": now - 0.9*day,
"concepts": ["decay", "half-life"]},
{"from_id": "alice", "to_id": "bob", "timestamp": now - 0.8*day,
"concepts": ["echo-coefficient"]},
{"from_id": "bob", "to_id": "alice", "timestamp": now - 0.7*day,
"concepts": ["shadow-detection", "gini"]},
]
msgs.extend(genuine)
# Adversary who has read F3.3: 50 msgs, each with a unique synonym of "hello"
# Balanced reciprocity (25+25) to maximize log(1+r)
hello_synonyms = [f"greeting-{i}" for i in range(50)]
for i in range(25):
msgs.append({"from_id": "eve", "to_id": "mallory",
"timestamp": now - 2*day + i*60,
"concepts": [hello_synonyms[i], hello_synonyms[i+25]]})
for i in range(25):
msgs.append({"from_id": "mallory", "to_id": "eve",
"timestamp": now - 1.5*day + i*60,
"concepts": [hello_synonyms[25+i]]})
edges = score_reciprocity(msgs, now=now)
genuine_edge = [e for e in edges.values() if "alice" in (e.source, e.target)][0]
adversarial_edge = [e for e in edges.values() if "eve" in (e.source, e.target)][0]
# The adversary WINS on F3.3 — this is the documented gap
assert adversarial_edge.reciprocity_f33 > genuine_edge.reciprocity_f33, \
(f"Expected adversary to beat genuine on F3.3 (known gap): "
f"adv={adversarial_edge.reciprocity_f33:.4f} vs gen={genuine_edge.reciprocity_f33:.4f}")
# Document the ratio for future F3.4 comparison
gap_ratio = adversarial_edge.reciprocity_f33 / max(genuine_edge.reciprocity_f33, 0.001)
assert gap_ratio > 1.5, \
f"Adversary should win by significant margin (gap_ratio={gap_ratio:.1f})"
def test_f33_adversarial_defeated_by_echo():
"""Full stack test: F3.3-aware adversary is caught by causal echo.
The adversary beats F3.3 alone but their concepts have zero echo
because no third party adopts 'greeting-17' independently.
This proves the stack (F3.3 + echo) catches what each layer alone misses."""
msgs = []
# Adversary pair: high F3.3, zero echo (concepts never appear elsewhere)
for i in range(10):
msgs.append({"from_id": "eve", "to_id": "mallory",
"timestamp": now - 2*day + i*100,
"concepts": [f"adversarial-concept-{i}"]})
for i in range(10):
msgs.append({"from_id": "mallory", "to_id": "eve",
"timestamp": now - 1.5*day + i*100,
"concepts": [f"adversarial-concept-{10+i}"]})
# Genuine pair: moderate F3.3, positive echo (concepts adopted by third party)
msgs.append({"from_id": "alice", "to_id": "bob",
"timestamp": now - 3*day, "concepts": ["reciprocity"]})
msgs.append({"from_id": "bob", "to_id": "alice",
"timestamp": now - 2.5*day, "concepts": ["reciprocity", "decay"]})
# Third party uses the same concept AFTER exposure
msgs.append({"from_id": "charlie", "to_id": "dave",
"timestamp": now - 1*day, "concepts": ["reciprocity"]})
# F3.3: adversary wins
edges = score_reciprocity(msgs, now=now)
adv = [e for e in edges.values() if "eve" in (e.source, e.target)][0]
gen = [e for e in edges.values() if "alice" in (e.source, e.target)][0]
assert adv.reciprocity_f33 > gen.reciprocity_f33, \
"Adversary should beat genuine on F3.3 alone"
# Echo: genuine wins (concept adopted by charlie)
echo = score_echo(msgs)
alice_echo = echo.get("alice", 0)
eve_echo = echo.get("eve", 0)
assert alice_echo > eve_echo, \
f"Genuine should beat adversary on echo: alice={alice_echo}, eve={eve_echo}"
# Eve's adversarial concepts should have zero echo
assert eve_echo == 0, \
f"Adversary concepts should have zero echo: {eve_echo}"
# Run all tests # Run all tests
tests = [v for k, v in sorted(globals().items()) if k.startswith("test_")] tests = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
passed = 0 passed = 0