Skip to content

Phase 11, part 1: a large memory store, the sorted index made optional, and LongMemEval-S in full - #32

Merged
rohan-hotdata merged 14 commits into
mainfrom
phase-11-large-store
Oct 22, 2026
Merged

rohan-hotdata merged 14 commits into
mainfrom
phase-11-large-store

Conversation

@rohan-hotdata

Copy link
Copy Markdown
Collaborator

What this does

Measures hotmemory with a large memory store, makes the sorted index on created_at an
option (off by default) because it made every write into a large table slow, and runs
LongMemEval-S on all 500 questions: 439 of 500 (87.8%).

How

  • HotdataStore.provision/open take sorted_index (src/hotmemory/hotdata.py). BM25
    stays; vector indexes stay experimental. Existing databases open as before.
  • Earlier phase 11 commits: guarded SQL INSERT for writes of ≤5 new rows, provision
    pages every database, current revisions read in batches of 500 keys, BM25 scope filter
    inside the search.
  • Bench (outside the package): bench/scale.py (scale harness, --prefill),
    bench/e2e.py (--background, --sample all, write timings, chunk_chars recorded),
    bench/diagnose.py (background runs, block SHA-256 check, as_of counts),
    bench/retrieval.py --data m.

Why

  • At 188,893 rows, a write of 1 to 12 rows took 8–20 s with the sorted index, ~1.4 s with
    BM25 alone, ~0.4 s with none, for INSERT and load alike. No HotdataStore query needs it.
  • A full run gives a score comparable with other systems, and the 54-question samples
    were too noisy.

Verification

  • make verify; driver tests against the local engine (26 passed, 1 expected failure),
    including 2 new tests for sorted_index.
  • Replays of samples A and B on new databases reproduced 48 and 46 at $0 before the full run.
  • LongMemEval-S, 500 questions: 439/500; 345/392 on questions no tuning used. One run, CI ±2.9.
  • Samples A and B over a prefilled store of 188,893 chunks: 39 and 35 (vs 48 and 46),
    with a diagnosis of 25 misses whose blocks all matched their run's SHA-256.
  • Not verified: cloud timings of the sorted-index change; the full run on the cloud engine.

Notes

  • Phase 11 stays open: next is the large store on LongMemEval-M, then the cue test.
  • Found, not fixed: recall applies as_of after the top k, so a store with many later
    records can leave a block half empty (planned in phase 13). One RESOURCE_LOCKED with a
    single writer, cause unknown.
  • The prefilled-store score includes contradiction between simulated users, which a real
    store scopes apart. See docs/benchmarks.md.
  • No issue exists for this phase.

…error, and compose drops the retired SQL writes setting
…fault

A write into a table of 188,893 rows took 8 to 20 s with the sorted index,
about 1.4 s with BM25 alone, and about 0.4 s with no index, for 1 row as for
12 rows, by INSERT or by load. No query of HotdataStore needs the index.
provision and open take sorted_index; a database that has the index opens
without the option.
…of a background run

bench/scale.py --prefill fills background/lme_s with the chunks of the sessions
outside samples A and B. bench/e2e.py --background runs each question in that
database, recalls over the question and the background, and records the time
of each write. --sample all runs every question. The result file records
chunk_chars, and bench/diagnose.py rebuilds the block of a background run,
checks its SHA-256, and counts the episodes kept by as_of.
…mEval-S in full

LongMemEval-S, all 500 questions, at the phase 10 configuration: 439 of 500
(87.8%), and 88.0% on the 392 questions outside samples A and B. Samples A and
B over a store with 188,893 chunks of other sessions: 39 and 35, against 48
and 46 from a fresh store, with the diagnosis of the loss. The cost of the BM25
and sorted indexes on writes. The plan and the roadmap move the large store
test to LongMemEval-M.
@rohan-hotdata
rohan-hotdata requested a review from a team as a code owner October 22, 2026 15:22
@rohan-hotdata
rohan-hotdata requested review from zfarrell and removed request for a team October 22, 2026 15:22
Comment thread docs/contracts.md Outdated

A store holds a lock across the read and the load of each write, so one store writes in
order. One process writes to a database. Two processes that put the same key can both read
the same current revision and both write the next one. Then the later load replaces the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: State that a guarded INSERT keeps the earlier row, not the later one (not blocking).

A put of a new key now goes through the guarded INSERT in _load (src/hotmemory/hotdata.py:590). Two processes that put the same new key both write id@1. The second INSERT finds the id and writes 0 rows, so the earlier write wins. "The later load replaces the earlier row" holds only for the upsert path. The same sentence appears in docs/guarantees.md:41. AGENTS.md requires both documents to match the behavior.

claude[bot]
claude Bot previously approved these changes Oct 22, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full diff was omitted from the review prompt. The patch was fetched with gh pr diff. Reviewed in full: src/hotmemory/hotdata.py, tests/test_hotdata.py, tests/test_hotdata_listing.py, tests/test_hotdata_retry.py, bench/scale.py, and the docs/contracts.md concurrency section. The other bench and docs files were not read line by line. CI checks were still pending when this review started.

… the same new key

The first revision of a new key, in a write of at most 5 new rows, goes by the
guarded INSERT, which skips an id that the table holds. A later revision, or a
write of more than 5 rows, goes by upsert load, where the later load wins.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full diff was omitted from the review prompt. This cycle reviewed the diff since adaa611 (docs/contracts.md, docs/guarantees.md) and checked it against src/hotmemory/hotdata.py:524-552. The earlier nit on the guarded INSERT is fixed: both documents now match the insert/upsert choice in _load_records.

@rohan-hotdata
rohan-hotdata merged commit 8eccc8e into main Oct 22, 2026
3 checks passed
@rohan-hotdata
rohan-hotdata deleted the phase-11-large-store branch October 23, 2026 08:21
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