Commit graph

2 commits

Author SHA1 Message Date
4c344782a7 test(hygiene): close every brain the find suite creates
tests/integration/find-*.test.ts and tests/unit/brainy/find*.test.ts each
opened one or more Brainy instances (via beforeAll/beforeEach) and never
closed them — the leaked instance's cadence timer stays armed for the rest
of the single-forked vitest run and keeps narrating into every later file.

find-unified-integration.test.ts was a real bug, not just a missing hook:
its afterAll called a no-op TestCleanup().cleanup() (nothing was ever
registered with it) and then discarded the brain reference with
`brain = null` — the brain was never actually closed.
2026-09-03 09:06:00 -07:00
5e720d17ae fix(find): orderBy is the order on every path, not only the metadata-only one
`find({ where, orderBy })` answered in field order; `find({ query, where,
orderBy })` and `find({ vector, where, orderBy })` answered in SCORE order.
The vector/filter block ranks the fused candidates by score, cuts the page and
returns early — and the tail's orderBy sort sits below that early return, so on
those paths it never ran. Nothing threw and nothing warned: the ordering request
was dropped in silence, and the two paths disagreed about what "ordered by rank"
means.

Where `connected` or `fusion` kept the tail alive the defect changed shape
rather than disappearing. The block had already CUT the page by score, so the
tail ordered the rows relevance had chosen — a correctly sorted page of the
wrong rows.

The early cut fires only once the candidate set reaches offset+limit rows, which
is why it read green for so long: below that threshold the block falls through
and the tail's sort does apply. An ordering that is correct until there is
enough data to matter.

THE LAW: an explicit orderBy displaces score as the ordering key on every path.
The candidate set the path produced is ordered IN FULL and the page is cut from
that ordering — "page last", the graph-first law applied to ordering rather than
to filtering. Score-ranked early paging stays exactly as it was for the default
case, where score IS the requested order.

The pin is differential against the metadata-only path, the one path that always
honoured orderBy. It is sized so the hybrid legs (each bounded at limit*2)
provably cover the filter universe, and that covering is asserted from the leg's
own output rather than assumed — orderBy orders the candidate set, it does not
enlarge it, and the pin claims nothing about recall.
2026-09-02 14:19:24 -07:00