phase: 162_search_recall_small_sources
**Phase 162 — final verification pass (all tasks already complete; verified + docs pass)** - Verified: `_fold` (NFKD+casefold, stdlib) inside `_normalize_name` — `BESTÅ`→`besta` question side, `BÅsta.md`→`basta` path side; A2 match classes/ranking/caps/bonus untouched; FTS/cosine/A8 untouched. - Verified: `grep_document` folds both sides via the imported `_fold` (no second copy); regex-teaching lines byte-identical; 3 copy sites updated. - Verified: `regenerate_overview` appends the deterministic `Sources: <name> (<k> doc|docs)` tail (happy path only; zero-doc + `LLMError` rows byte-identical; `build_overview_prompt`/`load_kb_overview`/`build_kb_section` untouched). - Verified: `TOOLS_SECTION` grep sentence updated + D4 search-discipline sentence present **verbatim**, immediately after the grep sentence; `PERSONA`/LOW pins byte-identical (`test_prompt_lock.py`). - Measured evidence (in `.agents/reports/162_…/task04_prefix_evidence_and_battery.md` + re-measured every run by `test_under_rank_is_measured_not_assumed`): pre-fix tokens `['build','best']` → IKEA doc rank 6 (outside top-5); post-fix `['build','besta']` → suggested #1, cosine unchanged 0.382. - `uv run pytest tests/e2e/test_search_recall_small_sources.py -v --no-cov` → **7 passed** (isolated); neighbours `test_kb_overview{,_freshness} test_name_signal_read_chips test_grep_regex_teaching test_harness_aligned_tools test_agent_document_tools test_tool_call_compact` → **24 passed**. - `uv run pytest --cov=app --cov-report=term-missing` → **3756 passed**, app coverage **99%** (>90%). - `uv run ruff check .` → All checks passed; `uv run pyright` → **0 errors**. - Completion criteria: fold both ways ✅ · `Sources:` tail ✅ · TOOLS_SECTION + D4 verbatim + re-cut pins ✅ · E2E green/battery recorded/full suite/coverage/lint ✅ · docs pass ✅ · commit + dir move = harness. - Battery: 5 phase-119 questions byte-identical to the phase-119 record (GATE PASS); the 2 Besta questions **skipped loudly** — verified the 2026-09-05 replica dump has zero `ikea` matches (`grep -c -i ikea data/bor_live_kb_replica.dump.sql` = 0); rank gate stays with the owner's live KB. - Docs fixed: README — overview-tail doc + `BOR_KB_OVERVIEW_MAX_CHARS` tail-cut constraint, the phase-162 search-discipline paragraph, per-phase (not per-story) E2E wording, new "Retrieval regression battery" section; AGENTS.md — rule 4 per-phase wording + battery command in Quick reference. (The overview's expected "AGENTS.md §6 tool table" does not exist in this repo — the grep contract line lives in README's tool table, already updated.) - Deviations (recorded, not assumed): `_fold` adds `casefold` (required for the pinned `ß → ss`); `①` NFKD-decomposes to `1` (the overview's parenthetical was wrong) and is excluded by `NAME_TOKEN_MIN_LEN`; pre-fix evidence lives in the reports dir because task files are read-only for this pass. - Owner follow-up A6 (runtime, not code): add the Tuning-tab steering note "IKEA's BESTÅ assembly PDF is a live source — search it as `BESTÅ` or `AA-1272068`". - Next pending phase: none — 162 is the only entry in `todo/` (harness moves it to `complete/`).
This commit is contained in:
@@ -367,7 +367,8 @@ def test_agent_tools_names_and_parameters() -> None:
|
||||
# teaching no-match line instead of a trusted miss.
|
||||
assert grep["description"] == (
|
||||
"Search the indexed documents for an exact string "
|
||||
"(case-insensitive) and return up to 20 matching lines "
|
||||
"(case- and accent-insensitive — accents fold: `besta` "
|
||||
"matches `BESTÅ`) and return up to 20 matching lines "
|
||||
"as `source/path:line: text` — a locator, not a "
|
||||
"context-adder: read the winner with `read` — for a "
|
||||
"large document, use the reported line number as "
|
||||
@@ -387,8 +388,11 @@ def test_agent_tools_names_and_parameters() -> None:
|
||||
assert set(grep_params["properties"]) == {"pattern", "path"}
|
||||
assert all(p["type"] == "string" for p in grep_params["properties"].values())
|
||||
assert grep_params["properties"]["pattern"]["description"] == (
|
||||
"The exact text to search for (a plain substring, "
|
||||
"not a regex — no '.*', no '\\.', no character classes)"
|
||||
"The exact text to search for (a plain "
|
||||
"substring — case- and accent-insensitive, "
|
||||
"accents fold: `besta` matches `BESTÅ` — "
|
||||
"not a regex — no '.*', no "
|
||||
"'\\.', no character classes)"
|
||||
)
|
||||
# Phase 72 (task 02): the bare-path contract is stated up front;
|
||||
# task 05 (live gate iterations 1-8): the one-known-document clause
|
||||
@@ -4000,6 +4004,27 @@ def test_origin_lines_image_doc_keeps_marker_position(
|
||||
# ---------- grep (the phase-68 A5 contract under the new name) ----------
|
||||
|
||||
|
||||
def test_grep_document_folds_accents_both_ways() -> None:
|
||||
"""Phase 162 (LOCKED A3): grep folds BOTH the pattern and each line
|
||||
through the shared ``app.rag.retriever._fold`` plus lowercase — an
|
||||
ASCII pattern hits accented content and an accented pattern hits
|
||||
ASCII content, one fold, never drifting from the name-hit path."""
|
||||
# ASCII pattern, accented content.
|
||||
assert agent.grep_document("The BESTÅ frame (AA-1272068-11-100)", "besta") == [
|
||||
(1, "The BESTÅ frame (AA-1272068-11-100)")
|
||||
]
|
||||
assert agent.grep_document("line one\nBÅsta shelf\nline three", "basta") == [
|
||||
(2, "BÅsta shelf")
|
||||
]
|
||||
assert agent.grep_document("café-au-lait", "cafe") == [(1, "café-au-lait")]
|
||||
# Accented pattern, ASCII content — the pattern's own accents fold.
|
||||
assert agent.grep_document("The besta frame", "BESTÅ") == [(1, "The besta frame")]
|
||||
# A genuinely non-matching folded pattern still returns no lines.
|
||||
assert agent.grep_document("The besta frame", "bestb") == []
|
||||
# The fold bridges Ä/Ö/Ü/ß too (the same _fold as name matching).
|
||||
assert agent.grep_document("Straße", "strasse") == [(1, "Straße")]
|
||||
|
||||
|
||||
def test_grep_document_case_insensitive_line_numbers() -> None:
|
||||
"""Case-insensitive fixed substring, 1-based line numbers, file order,
|
||||
repeated matches within a line collapse to one match (grep semantics)."""
|
||||
|
||||
Reference in New Issue
Block a user