Skip to content

chore(eval): cross-session memory eval + the OptMem evaluation it settled - #468

Merged
justrach merged 1 commit into
release/0.0.242from
chore/longhorizon-memory-eval
Aug 6, 2026
Merged

chore(eval): cross-session memory eval + the OptMem evaluation it settled#468
justrach merged 1 commit into
release/0.0.242from
chore/longhorizon-memory-eval

Conversation

@justrach

@justrach justrach commented Aug 6, 2026

Copy link
Copy Markdown
Owner

No behaviour change. Adds the harness that answers a question neither existing one can: after a session ends, can a fresh one recover what the first one learned?

live-ab measures token economics within a run; golden proves byte-identity of rendering. Neither crosses a session boundary, and neither exercises compaction more than incidentally. This validates #441, #391 and #411 under the conditions they were built for — and it reports 12/12 cold recall through 13 compactions with 0 fabricated tokens on v0.0.242.

The OptMem answer: not adopting

Evaluated because OptMem solves a real gap — a navigable hierarchical index over an append-only log — that #441's flat transcript does not.

base (v0.0.242) + OptMem
cold recall 12/12 8/12
steps completed 12/12 8/12 — budget exhausted
calls per completed step 3.2 7.5
input tokens 198,864 332,925 (+67%)
compactions 13 21

Its retention was flawless — 8 of 8 it stored survived the session boundary. It did not forget; it ran out of budget at step 8 of 12. The mechanism is the whole result: the base agent persisted with python3 probe.py step 9 | tee -a .probe-token-chain, folding durability into a tool call it was already making at zero marginal cost, while OptMem needs a separate memo note per fact plus a wake and prompted compressions. That is the #440 doctrine reached by the model unprompted, without a subsystem.

The tool is recorded, not vendored: the comparison arm needs LH_MEMO_BIN pointing at a binary the operator supplies.

Four design properties, three found the hard way

  1. Tokens are erased from disk when printedgrep -r afterwards finds nothing. Without this the eval measures re-reading, and every arm scores full marks by reading the file again.
  2. Steps are chained, not numbered. Measured, not assumed: a predictable 1..N sequence gets batched into single turns — 14 steps produced 9 api calls and 3 compactions. Chained, the same 14 produced 45 calls and 15 compactions.
  3. GRAFF_COMPACT_PCT, not GRAFF_CONTEXT. The latter applies only to models whose window graff cannot look up, so against a known-window model it is silently ignored and the run compacts zero times while appearing to work.
  4. Filler stays under the Tool results return handles by default above a size threshold (filesystem as the namespace) #440 handle threshold, so it accumulates in context rather than spilling to a handle.

Scoring separates three things

correct (matched against its own label), loose (present anywhere), and fabricated (label carrying the wrong value). loose caught a run scoring 0/14 exact that had actually retained all 14 — a labelling artifact, not amnesia. fabricated exists because on a cold recall an agent that invents plausible values is worse than one that admits it cannot recover them, and a hits-only score hides that.

An invalid round, recorded deliberately

The first attempt was single-session. Both arms scored 18/18 and OptMem looked like +10.7% cost for no benefit — tidy, plausible, and entirely unfounded: memo note was called zero times and LOG.txt was empty. Two findings survive it: the model ignored instructions marked "mandatory" despite a correct AGENTS.md and an executable at the documented path, which is an adoption risk for any memory layer depending on the model volunteering to write; and a single-session test cannot evaluate a cross-session tool.

The general lesson, and why memo_notes/memo_log_lines are in the record: check the mechanism was exercised before believing the score.

Caveats stated in the results file

n=1 per arm, so deltas are directional. The 60-call cap is a chosen parameter — OptMem would likely have finished without it — though the 2.3× per-step cost ratio is cap-independent. Both arms were told a later session would need the data, which does real work: in the un-hinted round the agent persisted nothing at all.

…t settled

Neither existing harness crosses a session boundary: live-ab measures token
economics within a run, golden proves byte-identity of rendering. This one
builds durable state in one session and makes a FRESH process recover it,
which is the only way to test whether #441/#391/#411 actually work.

Four properties had to be there, three of them found the hard way:

- Tokens are erased from disk when printed, so the eval measures memory
  rather than re-reading. A fact still on disk is one any competent agent
  simply reads again.
- Steps are chained rather than numbered, because a predictable sequence
  gets batched: 14 predictable steps produced 9 api calls and 3 compactions,
  the same 14 chained produced 45 calls and 15 compactions.
- Compaction is forced with GRAFF_COMPACT_PCT. GRAFF_CONTEXT applies only to
  models whose window graff cannot look up, so against a known model it is
  silently ignored and the run compacts zero times while appearing to work.
- Scoring separates correct / anywhere / fabricated, which caught a run
  reporting 0/14 exact that had in fact retained all 14, and which keeps an
  agent that invents plausible values from scoring like one that recalls.

The OptMem comparison is recorded rather than vendored: the arm needs
LH_MEMO_BIN pointing at a binary the operator supplies.

Result: base recovered 12/12 cold with 0 fabricated; OptMem retained 8 of
the 8 it stored but exhausted its call budget at step 8 of 12, costing 2.3x
the calls per step. The base agent persisted by folding `| tee -a` into a
tool call it was already making, which is the #440 doctrine reached without
a subsystem.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
@justrach
justrach merged commit 0ed169b into release/0.0.242 Aug 6, 2026
6 checks passed
@justrach
justrach deleted the chore/longhorizon-memory-eval branch August 6, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant