feat(learn): A/B experiment runner -- registered manifests, paired arms, bootstrap and McNemar (decision-engine task 7)

learn/experiments.py: YAML manifests under plane/experiments/<id>.yaml,
digest-checked at register, run and analyse time; `experiment`,
`arm_outcome` and `experiment_result` rows; paired arms in a seeded
repository order with a per-unit coin; arm A replay-only at $0; canary
replicates under a fresh cache salt; repository-cluster paired bootstrap,
exact McNemar, two O'Brien-Fleming looks, adopt/reject/equivalent/
inconclusive. `ousast learn experiment register|units|run|analyse`.
Program: `ProgramSpec.sampling = retrieval_ensemble` (k samples at
temperature 0 over k disjoint retrieved example sets; default unchanged);
`Caller.salt`; `retrieve(exclude=)`. verify: OUSAST_VERIFY_CALLERS=off.
Manifests exp-001-known-callers (plane arms, units pending) and
exp-002-retrieval-ensemble (slice-2 incumbents, ceiling $4) -- not run.
18 scripted tests; module audit regenerated (151 modules).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-10-02 16:04:33 +02:00
co-authored by Claude Fable 5.1
parent a90e570f48
commit fbc3220bbe
14 changed files with 1681 additions and 35 deletions
@@ -1,7 +1,7 @@
{
"modules": 150,
"modules": 151,
"counts": {
"load_bearing": 145,
"load_bearing": 146,
"standalone_capability": 5
},
"orphaned": [],
@@ -355,6 +355,7 @@
"learn.evaluate",
"learn.examples",
"learn.excerpt",
"learn.experiments",
"learn.features",
"learn.folds",
"learn.labels",
@@ -390,7 +391,8 @@
"reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [
"learn.cli",
"learn.evaluate"
"learn.evaluate",
"learn.experiments"
]
},
{
@@ -408,7 +410,8 @@
"reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [
"learn.cli",
"learn.compile"
"learn.compile",
"learn.experiments"
]
},
{
@@ -419,6 +422,7 @@
"learn.cli",
"learn.compile",
"learn.evaluate",
"learn.experiments",
"learn.folds",
"learn.program",
"learn.retrieve"
@@ -435,6 +439,14 @@
"plane.harvest"
]
},
{
"module": "learn.experiments",
"classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [
"learn.cli"
]
},
{
"module": "learn.features",
"classification": "load_bearing",
@@ -452,6 +464,7 @@
"learn.cli",
"learn.compile",
"learn.evaluate",
"learn.experiments",
"learn.program",
"learn.retrieve"
]
@@ -487,7 +500,8 @@
"importers": [
"learn.cli",
"learn.compile",
"learn.evaluate"
"learn.evaluate",
"learn.experiments"
]
},
{
@@ -831,6 +845,7 @@
"learn.compile",
"learn.embeddings",
"learn.examples",
"learn.experiments",
"learn.program",
"plane.egress",
"plane.engine_alerts",
@@ -855,6 +870,7 @@
"learn.cli",
"learn.compile",
"learn.embeddings",
"learn.experiments",
"learn.program",
"plane.generate",
"plane.tasks.roles",
@@ -920,7 +936,7 @@
{
"module": "plane.memory",
"classification": "load_bearing",
"reason": "harnessx-removal Req 6.1/6.4: the memory store (file, MinIO), ingest and fact reuse; `ousast plane remember`",
"reason": "harnessx-removal Req 6.1/6.4: the memory store (file, S3), ingest and fact reuse; `ousast plane remember`",
"importers": [
"cli",
"improve.memory",
@@ -928,6 +944,7 @@
"learn.compile",
"learn.embeddings",
"learn.examples",
"learn.experiments",
"learn.program",
"plane.generate",
"plane.tasks.loop",