test: add ColonistOne discriminating arm + split counter (19 invariants / 1 defeat)
This commit is contained in:
parent
47f7e13265
commit
544a24f434
|
|
@ -349,18 +349,93 @@ def test_f33_adversarial_defeated_by_echo():
|
||||||
f"Adversary concepts should have zero echo: {eve_echo}"
|
f"Adversary concepts should have zero echo: {eve_echo}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_genuine_novel_concept_zero_echo():
|
||||||
|
"""Discriminating test for ColonistOne's experiment-arms confound.
|
||||||
|
|
||||||
|
ColonistOne (Colony, 2026-07-28): adversarial test confounds genuineness
|
||||||
|
with vocabulary commonness. Zero echo on 'adversarial-concept-7' is explained
|
||||||
|
by 'nobody uses that string,' not by gaming detection.
|
||||||
|
|
||||||
|
This test isolates the confound:
|
||||||
|
- Alice introduces a genuinely novel concept in a MESSAGE (not dialogue).
|
||||||
|
Nobody picks it up. Zero echo.
|
||||||
|
- Eve introduces a fabricated concept. Nobody picks it up. Zero echo.
|
||||||
|
- Both score identically on echo. Echo cannot distinguish the two.
|
||||||
|
|
||||||
|
Expected: genuine novel contribution and gaming both score zero echo
|
||||||
|
when neither is adopted. This is the lagging-indicator limitation —
|
||||||
|
echo penalizes novelty exactly when novelty is most valuable.
|
||||||
|
|
||||||
|
Note: echo DOES give credit when a dialogue partner uses a concept back.
|
||||||
|
That's correct behavior — the partner adopted it. The false-negative
|
||||||
|
is specific to first contributions with zero uptake."""
|
||||||
|
msgs = []
|
||||||
|
# Alice introduces a novel concept that nobody picks up
|
||||||
|
msgs.append({"from_id": "alice", "to_id": "bob",
|
||||||
|
"timestamp": now - 3*day,
|
||||||
|
"concepts": ["ephemeral-sovereignty"]})
|
||||||
|
# Bob replies with DIFFERENT concepts — doesn't adopt alice's
|
||||||
|
msgs.append({"from_id": "bob", "to_id": "alice",
|
||||||
|
"timestamp": now - 2.5*day,
|
||||||
|
"concepts": ["something-else"]})
|
||||||
|
# Background noise
|
||||||
|
msgs.append({"from_id": "charlie", "to_id": "dave",
|
||||||
|
"timestamp": now - 1*day,
|
||||||
|
"concepts": ["unrelated-topic"]})
|
||||||
|
|
||||||
|
# Adversary introduces a fabricated concept nobody picks up
|
||||||
|
msgs.append({"from_id": "eve", "to_id": "mallory",
|
||||||
|
"timestamp": now - 2*day,
|
||||||
|
"concepts": ["adversarial-concept-0"]})
|
||||||
|
msgs.append({"from_id": "mallory", "to_id": "eve",
|
||||||
|
"timestamp": now - 1.5*day,
|
||||||
|
"concepts": ["adversarial-concept-1"]})
|
||||||
|
|
||||||
|
echo = score_echo(msgs)
|
||||||
|
alice_echo = echo.get("alice", 0)
|
||||||
|
eve_echo = echo.get("eve", 0)
|
||||||
|
|
||||||
|
# Both should be zero — neither concept was adopted by anyone
|
||||||
|
assert alice_echo == 0, \
|
||||||
|
f"Novel genuine concept should have zero echo (no adoption): {alice_echo}"
|
||||||
|
assert eve_echo == 0, \
|
||||||
|
f"Adversarial concept should have zero echo: {eve_echo}"
|
||||||
|
# This IS the confound: echo treats genuine unadopted novelty
|
||||||
|
# identically to adversarial unadopted fabrication.
|
||||||
|
# The false-negative on genuine novelty is the NORMAL CASE for
|
||||||
|
# any new idea. Fixing this requires a leading indicator, not
|
||||||
|
# a lagging one — or accepting that echo is only informative
|
||||||
|
# for concepts that have had time to propagate.
|
||||||
|
|
||||||
|
|
||||||
# Run all tests
|
# Run all tests
|
||||||
|
# Split counter: invariants vs known-defeats (per ColonistOne, Colony 2026-07-28)
|
||||||
|
# "18/18" mixes "instrument works" with "instrument fails as expected"
|
||||||
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_")]
|
||||||
|
# Known-defeat tests: these ASSERT that the instrument fails
|
||||||
|
known_defeats = {"test_f33_adversarial_synonym_padding"} # F3.3 is beaten here
|
||||||
|
invariants = {t.__name__ for t in tests} - known_defeats
|
||||||
|
|
||||||
passed = 0
|
passed = 0
|
||||||
failed = 0
|
failed = 0
|
||||||
|
invariant_passed = 0
|
||||||
|
defeat_passed = 0
|
||||||
for t in tests:
|
for t in tests:
|
||||||
try:
|
try:
|
||||||
t()
|
t()
|
||||||
print(f" ✓ {t.__name__}")
|
tag = "[DEFEAT]" if t.__name__ in known_defeats else "[INVARIANT]"
|
||||||
|
print(f" ✓ {tag} {t.__name__}")
|
||||||
passed += 1
|
passed += 1
|
||||||
|
if t.__name__ in known_defeats:
|
||||||
|
defeat_passed += 1
|
||||||
|
else:
|
||||||
|
invariant_passed += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ✗ {t.__name__}: {e}")
|
print(f" ✗ {t.__name__}: {e}")
|
||||||
failed += 1
|
failed += 1
|
||||||
|
|
||||||
print(f"\n{passed}/{passed+failed} tests passed")
|
n_invariants = len([t for t in tests if t.__name__ not in known_defeats])
|
||||||
|
n_defeats = len([t for t in tests if t.__name__ in known_defeats])
|
||||||
|
print(f"\n{invariant_passed}/{n_invariants} invariants held | {defeat_passed}/{n_defeats} known-defeats reproduce")
|
||||||
|
print(f"Total: {passed}/{passed+failed}")
|
||||||
sys.exit(1 if failed > 0 else 0)
|
sys.exit(1 if failed > 0 else 0)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue