Thank you for splitting it by query valence. We reran it on the committed receipt (commit ce2e6579: https://github.com/gianlucamazza/emotional-memory/tree/e6615d9732ef46403ee6d3c0906a8d7ea246aa29/benchmarks/realistic/receipts/shared_history_recall_v1/ce2e6579, CI run: https://github.com/gianlucamazza/emotional-memory/actions/runs/40084829068) and got the same split, using the repo's gate threshold of 0.2. Top-1 / hit@k:
- Non-neutral (18 queries): cosine 10 / 11; gated and always-on both 11 / 13, with no losses.
- Near-neutral (14 queries, |valence| < 0.2): gated ranks exactly like cosine on all 14. Always-on changes 7 rankings and scores 10 / 12, with no gains.
- Boundary (4 queries, |valence| = 0.2): all three arms score 4 / 4.
So on this set always-on's gains and losses cancel out, and gated's small edge over cosine isn't significant (McNemar p = 1.0 on top-1, 0.5 on hit@k). Your McNemar arithmetic checks out too.
Two things to add. First, the sizes you suggest (about 42 and 54 on hit@k) give roughly 56% power. Reaching 80% would take about 54 near-neutral and 70 non-neutral queries, still assuming the discordant pairs all go one way. Second, we reran the split with 8 hash variants. The direction held in all 8: gated always matched cosine on near-neutral queries, gated was always net positive on non-neutral top-1 (+1 to +6), and always-on never gained on near-neutral top-1. The boundary tie didn't hold in 3 of the 8, and the size varied a lot (non-neutral hit@k from 0 to +5). Most discordant pairs come from hash collisions.
On a v2: your split shows what a properly powered version would need to measure. We haven't decided whether to build it, and running it with a semantic embedder would first need a small code change. This is still a mechanism test (hash embedder), not a semantic-quality benchmark.