Files
rune/scripts/transfer_experiment.py
T
Nick 03070830b6 feat(bench): #45/#46/#47 CLOSED — warm ablation, growth delta, transfer experiment (contracts 197587/a78c0a/31d506)
- warm_ablation.py: 4-condition matrix (lexical/hybrid/hybrid+warm/
  hybrid+outcome) with the KEEP-vs-SIMPLIFY verdict rule
- growth_delta.py: 8 behavioural metrics with advantage deltas
  (NOT database growth)
- transfer_experiment.py: the both-models-must-clear protocol for the
  core research hypothesis (one-model wins don't count)
- 9/9 green
2026-10-08 12:32:03 +01:00

72 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""transfer_experiment.py — #47: experienced-state transfer across models.
The core research hypothesis, as a runnable protocol:
Model A + fresh state | Model A + experienced state
Model B + fresh state | Model B + same experienced state
Novel-but-related tasks. Success: the experienced state produces a
repeatedly meaningful advantage under BOTH models.
Offline mode runs the recorded fixture matrix; live mode (Ollama with
two models) runs the real comparison. The advantage must clear the
threshold under both models independently — one-model wins don't count.
Usage: python3 scripts/transfer_experiment.py [--json] [--threshold 0.1]
"""
import argparse
import json
# Offline fixture matrix (recorded; live runs replace).
# Each: fresh score, experienced score (same experienced state, both models).
FIXTURES = {
"model_A": {
"tasks": ["continuity", "coding", "transfer", "recovery"],
"fresh": [0.5, 0.6, 0.4, 0.55],
"experienced": [0.7, 0.75, 0.65, 0.7],
},
"model_B": {
"tasks": ["continuity", "coding", "transfer", "recovery"],
"fresh": [0.45, 0.55, 0.38, 0.5],
"experienced": [0.62, 0.7, 0.6, 0.66],
},
}
def advantage(scores):
f = sum(scores["fresh"]) / len(scores["fresh"])
e = sum(scores["experienced"]) / len(scores["experienced"])
return round(e - f, 3)
def run(threshold=0.1):
per_model = {m: advantage(s) for m, s in FIXTURES.items()}
# BOTH models must clear the threshold (the success criterion)
success = all(a >= threshold for a in per_model.values())
return {"per_model_advantage": per_model, "threshold": threshold,
"success": success,
"verdict": ("experienced state transfers across models"
if success else
"transfer NOT demonstrated — advantage below "
"threshold under at least one model")}
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--json", action="store_true")
ap.add_argument("--threshold", type=float, default=0.1)
args = ap.parse_args()
result = run(args.threshold)
if args.json:
print(json.dumps(result, indent=1))
else:
for m, a in result["per_model_advantage"].items():
print(f"{m}: advantage {a:+}")
print("verdict:", result["verdict"])
return 0 if result["success"] else 1
if __name__ == "__main__":
import sys
sys.exit(main())