Files
ely-eye/backend/tests/test_text_index.py
T
ZacharyZhang-NY 4ab36cd5eb Make the proof suite say what it actually ran
The suite had fifteen checks that could not lose. The visual HashHop arena
painted a cyan line and a white ring on the answer slot, then asked the model
to find the answer by looking; the collector re-rolled puzzles until the
running rate crossed its target; the cache check passed if any layer had ever
recorded an entry; the repository check passed on a call graph built in memory
without touching the store; the research-module check asserted non-empty lists
of SHA256-derived placeholder vectors and so could not fail.

Each check now answers for one claim and reports a verdict the reader can act
on: passed, failed, deferred, or removed. A deferred row names what is missing
and the command that would settle it; a removed row says why the old claim was
withdrawn. The suite verdict is failed > deferred > passed, so a claim that
never ran holds the whole report back from saying "proven".

- evals.py (2427 lines) becomes the proofs/ package; largest module 445 lines.
- proofs/__main__.py deleted: it duplicated PRDProofSuite.latest() with a
  different glob. proofs/table.py renders; latest-proof-suite is the one face
  and exits 1 on a failed verdict.
- The arena paints nothing. The puzzle id is printed on its tile instead,
  because removing the ink without it removes the question.
- HashHop runs a fixed 8 puzzles per depth instead of re-rolling to target.
- The contradiction corpus moves from code to contradiction_scenarios.json;
  the check stays deferred while the corpus is the one this repo authored.
- The cache check compiles a nonce question over a real atom twice and reads
  the miss to hit movement; an empty store fails instead of agreeing by luck.
- The repository check requires rows in the store; the research-module check is
  removed.

Two product bugs surfaced on the way:
- text_index.fts_query joined Latin terms with a space, which FTS5 reads as
  AND, so a question longer than its answer retrieved nothing. Terms are ORed
  and bm25 rank orders the candidates.
- profiles.windows_path_to_wsl prefixed /mnt/ onto an already-POSIX path with
  an empty drive, producing /mnt//home/... and failing every launcher probe.

Verification: 168 passed (pytest backend/tests bench/tests); ruff clean on the
proofs package, cli.py, text_index.py, profiles.py, and both test files; mypy
clean on 16 files with a fresh cache; pyright reports 0 errors on proofs/ and
the test file. Ruff debt elsewhere is unchanged: 19 errors in seven files this
commit does not touch, measured against the same files at HEAD.
2026-10-07 18:39:46 -04:00

111 lines
4.5 KiB
Python

"""Checks for the FTS normalizer, run against a real FTS5 table.
String equality alone would pass a normalizer SQLite cannot use, so every acceptance case
here inserts indexed text and asks the engine the question the user would ask.
"""
from __future__ import annotations
import sqlite3
import pytest
from ely_eye.text_index import fts_query, index_text
def _fts(rows: list[str]) -> sqlite3.Connection:
connection = sqlite3.connect(":memory:")
connection.execute("CREATE VIRTUAL TABLE fts USING fts5(original UNINDEXED, text, tokenize = 'unicode61')")
connection.executemany("INSERT INTO fts(original, text) VALUES (?, ?)", [(row, index_text(row)) for row in rows])
return connection
def _hits(connection: sqlite3.Connection, query: str) -> list[str]:
return [row[0] for row in connection.execute("SELECT original FROM fts WHERE fts MATCH ?", (fts_query(query),))]
def _ranked(connection: sqlite3.Connection, query: str) -> list[str]:
"""Matches in bm25 order: the answer that covers more of the question should come first."""
return [
row[0]
for row in connection.execute(
"SELECT original FROM fts WHERE fts MATCH ? ORDER BY rank", (fts_query(query),)
)
]
def test_index_text_splits_a_chinese_sentence_into_characters() -> None:
assert index_text("我们的钥匙放在玄关抽屉里") == "我 们 的 钥 匙 放 在 玄 关 抽 屉 里"
def test_index_text_splits_identifiers_a_user_cannot_guess_the_casing_of() -> None:
assert index_text("func SearchAtoms") == "func search atoms"
assert index_text("def search_atoms(self) -> None:") == "def search atoms self none"
assert index_text("HTTPServer2 listens on 8765") == "http server 2 listens on 8765"
def test_index_text_folds_full_width_letters_that_search_would_miss() -> None:
assert index_text("Search Atoms") == "search atoms"
def test_fts_query_phrases_cjk_and_prefixes_latin() -> None:
assert fts_query("钥匙") == '"钥 匙"'
assert fts_query("search atoms") == '"search"* OR "atoms"*'
def test_a_long_question_reaches_the_answer_that_covers_most_of_its_words() -> None:
"""AND over every word answers a long question with nothing; bm25 picks the best candidate."""
connection = _fts(
[
"PRD requirements prove long context memory, HashHop proof, and adapter training.",
"The adapter was trained for 29 steps on 37 samples.",
"Unrelated notes about the weather.",
]
)
question = "Which Ely-Eye PRD requirements prove long context memory, HashHop, and adapters?"
hits = [
row[0]
for row in connection.execute(
"SELECT original FROM fts WHERE fts MATCH ? ORDER BY rank", (fts_query(question),)
)
]
assert hits[0].startswith("PRD requirements prove")
assert "Unrelated notes about the weather." not in hits
def test_fts_query_refuses_a_query_with_nothing_to_match() -> None:
for empty in ("", " ", "?!。"):
with pytest.raises(ValueError, match="needs at least one searchable word"):
fts_query(empty)
def test_a_chinese_question_finds_the_chinese_memory() -> None:
connection = _fts(["我们的钥匙放在玄关抽屉里", "The keys are in the kitchen drawer"])
assert _hits(connection, "钥匙") == ["我们的钥匙放在玄关抽屉里"]
def test_a_cjk_phrase_will_not_match_its_characters_scattered_apart() -> None:
connection = _fts(["钥匙在抽屉", "匙 在 钥"])
assert _hits(connection, "钥匙") == ["钥匙在抽屉"]
def test_an_english_query_finds_the_identifier_it_names() -> None:
connection = _fts(["func SearchAtoms(ctx context.Context)", "func ListCartridges()"])
assert _hits(connection, "search atoms") == ["func SearchAtoms(ctx context.Context)"]
def test_a_prefix_reaches_the_word_it_grew_into() -> None:
connection = _fts(["the atom was forgotten", "unrelated text"])
assert _hits(connection, "atom") == ["the atom was forgotten"]
assert _hits(connection, "forg") == ["the atom was forgotten"]
def test_a_mixed_query_ranks_the_memory_holding_both_halves_first() -> None:
"""A query with a Chinese half and an English half must prefer the memory holding both."""
connection = _fts(["钥匙放在 drawer 里", "钥匙在玄关", "the drawer is empty"])
ranked = _ranked(connection, "钥匙 drawer")
assert ranked[0] == "钥匙放在 drawer 里"
assert set(ranked) == {"钥匙放在 drawer 里", "钥匙在玄关", "the drawer is empty"}