The second review round of p2-4 measured three behaviour defects behind the
as_of feature it had just accepted, and all three came from one mistake: the
code asked "is this memory current?" in three places and answered differently.
- A memory that has closed kept no vector at all, so the dense leg could only
exclude an old fact, never recall it. Vectors now follow existence, not
currency; `_allowed` decides who may see one.
- "Open right now" meant `valid_to IS NULL` in the view and in the words leg
but `valid_to IS NULL OR valid_to > now` in the vector leg, so a supersede
booked for next year hid a fact that is still true today. All three now read
the same rule; schema v12 records the change and the upgrade drops the old
view, since CREATE VIEW IF NOT EXISTS would have kept the old body.
- The dense as_of test was名不副实: dense is off by default, so it passed while
the vector side had no coverage. It now turns dense on with a stand-in model
and pins both `VectorIndex.search(as_of=…)` and the plumbing in retrieval.
Five mutations, each caught by exactly one test: the dense as_of branch, the
retrieval hand-off, the three vector reads, the words-leg currency, the view.
Record side: the round-2 line quoted a D-list I had misread out of the
reviewer's PASS tables (cf2de31 fixed those, and they were its precision notes,
not its findings), the stale line-number parenthetical, an acceptance grep that
scanned CHECKLIST's own quotations, and a Gaps.md tally that disagreed with its
own table (8 closed, 3 closed with reservations, 1 partial).
Gates: 411 passed; ruff, filesize, audit 33/2/6 clean; pyright 0 on the six
touched files; mypy cold cache Success on the same six; scripts/key_test.sh
exit 0 (6 PASS, 1 NOT MEASURED).
The key test in Gaps.md §6 asks what was true last week. It could not be
answered: search_atoms joined v_atoms_current, so a superseded memory is
unreachable no matter what since/until says — those two fields bound when a
memory was true, not which moment the store answers from.
SearchFilters.as_of moves that moment. Without it the words leg repeats the
view's currency predicate verbatim; with it a memory answers when
valid_from <= as_of < valid_to, its event time has arrived, and it is inside
its retention. archived_at is ignored on purpose: archival is a storage tier,
not a claim about the world, so an archived memory still answers for the time
before it was archived. The dense leg reads the same window through
vector_index._allowed, so the two legs cannot disagree about what existed.
scripts/key_test.sh runs the seven §6 scenarios end to end against one live
store — HTTP, the Go MCP binary over stdio, and the CLI mounting cartridges.
Six pass. The seventh, "a cartridge saves compute", is reported NOT MEASURED
rather than passed: it claims time-to-first-token and a cache-hit rate, no
generator has ever run here, and there is no compile or cache route to observe
even the second half.
Gates: pytest -q 406 passed; ruff clean; filesize OK; pyright 0 on the seven
touched files; mypy cold cache Success on the same seven; key test exit 0.