MemHarness (arXiv 2607.28272, 2026-07-30) reports the result that matters most for Cortex's injection hooks: injecting retrieved memory unmodified is worse than injecting nothing at all.
The measurement
Table 2, ALFWorld:
| Arm |
ALFWorld |
WebShop |
| RL only, no memory |
76.4% |
66.1% |
| RL + raw memory (verbatim, no reconstruction) |
70.1% |
72.6% |
| MemHarness (critique + reconstruct) |
85.2% |
75.6% |
Their conclusion, verbatim: "Injecting unrefined memory… hurts ALFWorld performance. This proves verbatim replay introduces state-mismatch noise, which our reconstruction mechanism effectively mitigates." Raw memory cost 6.3 points against the no-memory baseline. They call this negative transfer: "A memory may be semantically relevant to the task yet inappropriate for the current interaction state, because it was formed under different environmental conditions."
Counterfactual probe (Table 4a): rejection rates rise from 8.7% to 13.3% when the source state is randomised — the critique step is genuinely reading state, not pattern-matching relevance.
Current state (verified 2026-08-06)
mcp_server/hooks/session_start.py injects anchored + hot memories directly into the context block (see its module docstring, and _fetch_anchors at line 130), stamped with injection receipts via handlers/injection_receipts.py. Nothing between selection and injection compares the memory's formation context to the current one.
The nearest existing mechanism is not equivalent: core/abstention_gate.py is a fine-tuned DistilBERT trained on BEAM (query, passage, relevant/irrelevant) pairs — its own docstring says it "filters retrieval results that don't actually answer the query." That is a relevance gate. MemHarness's critique is an applicability gate: same relevance, different state. A memory can pass BEAM relevance and still be exactly the negative-transfer case. core/memory_rules.py filtering and core/reranker.py scoring are likewise relevance-shaped.
Note the asymmetry in their own numbers — raw memory helped WebShop (+6.5) while hurting ALFWorld (−6.3). So the effect is task-dependent and we must measure it on our own workload rather than assume the direction.
Ask
Insert a critique step between selection and injection that compares each candidate's formation context against the current session state and returns retain / revise / reject, plus an explicit "no applicable memory" path (their <EMPTY> → fall back to self-reasoning) rather than injecting a weak best-effort set.
Cortex stores what is needed to attempt this: memories carry provenance and timestamps, and core/staleness.py already scores file-reference staleness — which is a narrow special case of exactly this question.
Acceptance criteria (§13 A3 / F1 are the crux here)
- Retain, revise, and reject arms each map to a test asserting the observable effect, including emission of the reject signal itself — not merely that a downstream count changed. A silently-dropped memory is the FlashRank failure mode repeated.
- The
<EMPTY> / no-applicable-memory path is tested, and the nominal path is asserted quiet (§13 G4 — negative assertions where absence is the behaviour).
- Injection receipts must continue to resolve through
/why after the critique step: a rejected memory must be distinguishable in the receipt from one never selected, or the blame path silently changes meaning.
- Before/after measured on our own workload with paired arms at one commit. If raw-vs-critiqued shows no effect on our tasks, that negative result is recorded in
docs/provenance/ — not quietly dropped.
- Zero surviving non-equivalent mutants on changed files (§12).
Relates to #360 (provenance coverage).
MemHarness (arXiv 2607.28272, 2026-07-30) reports the result that matters most for Cortex's injection hooks: injecting retrieved memory unmodified is worse than injecting nothing at all.
The measurement
Table 2, ALFWorld:
Their conclusion, verbatim: "Injecting unrefined memory… hurts ALFWorld performance. This proves verbatim replay introduces state-mismatch noise, which our reconstruction mechanism effectively mitigates." Raw memory cost 6.3 points against the no-memory baseline. They call this negative transfer: "A memory may be semantically relevant to the task yet inappropriate for the current interaction state, because it was formed under different environmental conditions."
Counterfactual probe (Table 4a): rejection rates rise from 8.7% to 13.3% when the source state is randomised — the critique step is genuinely reading state, not pattern-matching relevance.
Current state (verified 2026-08-06)
mcp_server/hooks/session_start.pyinjects anchored + hot memories directly into the context block (see its module docstring, and_fetch_anchorsat line 130), stamped with injection receipts viahandlers/injection_receipts.py. Nothing between selection and injection compares the memory's formation context to the current one.The nearest existing mechanism is not equivalent:
core/abstention_gate.pyis a fine-tuned DistilBERT trained on BEAM (query, passage, relevant/irrelevant) pairs — its own docstring says it "filters retrieval results that don't actually answer the query." That is a relevance gate. MemHarness's critique is an applicability gate: same relevance, different state. A memory can pass BEAM relevance and still be exactly the negative-transfer case.core/memory_rules.pyfiltering andcore/reranker.pyscoring are likewise relevance-shaped.Note the asymmetry in their own numbers — raw memory helped WebShop (+6.5) while hurting ALFWorld (−6.3). So the effect is task-dependent and we must measure it on our own workload rather than assume the direction.
Ask
Insert a critique step between selection and injection that compares each candidate's formation context against the current session state and returns retain / revise / reject, plus an explicit "no applicable memory" path (their
<EMPTY>→ fall back to self-reasoning) rather than injecting a weak best-effort set.Cortex stores what is needed to attempt this: memories carry provenance and timestamps, and
core/staleness.pyalready scores file-reference staleness — which is a narrow special case of exactly this question.Acceptance criteria (§13 A3 / F1 are the crux here)
<EMPTY>/ no-applicable-memory path is tested, and the nominal path is asserted quiet (§13 G4 — negative assertions where absence is the behaviour)./whyafter the critique step: a rejected memory must be distinguishable in the receipt from one never selected, or the blame path silently changes meaning.docs/provenance/— not quietly dropped.Relates to #360 (provenance coverage).