phase: 162_search_recall_small_sources
Build and Push Containers / build-and-push-app (push) Successful in 1m50s
Build and Push Containers / build-and-push-db (push) Successful in 14s

**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:
2026-10-07 01:42:01 -04:00
parent 690fd98036
commit eebc824636
48 changed files with 2685 additions and 80 deletions
+69 -16
View File
@@ -17,6 +17,7 @@ import hashlib
from app.rag.prompts import (
ORIGIN_RULE,
PERSONA,
SEARCH_DISCIPLINE_RULE,
SUGGEST_INTRO,
TOOLS_SECTION,
_base,
@@ -87,9 +88,34 @@ def test_high_and_low_bases_byte_locked() -> None:
#: inserted — the prefix (the ``ls``-clause opening) and the suffix
#: (the discipline-rules ending) survived byte-identical, so they are
#: the same anchors as pre-phase-145; the pre-phase-145 sha/length are
#: kept below for the diff-style pin.
TOOLS_SECTION_SHA256 = "41a84885be98d4e15b95205694d59d364296a30e27758d39ae737881d5bacaa7"
TOOLS_SECTION_LEN = 3279
#: kept below for the chained diff-style pin. RE-CUT again for phase 162
#: (task 03, LOCKED A3+A4): the ``grep`` sentence's ``(case-insensitive)``
#: parenthetical widened to the folded contract ``(case- and
#: accent-insensitive — accents fold: besta matches BESTÅ)``, and the
#: LOCKED search-discipline sentence (:data:`SEARCH_DISCIPLINE_RULE`) was
#: inserted immediately after the grep sentence (before the ``For a normal
#: search pass`` clause). Only those two byte-groups moved — the prefix
#: (the ``ls``-clause opening) and the suffix (the discipline-rules
#: ending) survive byte-identical; the pre-phase-162 sha/length are kept
#: below for the chained diff-style pin.
TOOLS_SECTION_SHA256 = "988642f9dc6bb2a4a1d44a83b5368ff4cdb9df4e181b2fe3dc2fb241b1857595"
TOOLS_SECTION_LEN = 3818
# The pre-phase-162 anchors — the section BEFORE phase 162's grep-fold +
# search-discipline insertion. Kept for the chained diff-style pin.
TOOLS_SECTION_PRE_PHASE_162_SHA256 = (
"41a84885be98d4e15b95205694d59d364296a30e27758d39ae737881d5bacaa7"
)
TOOLS_SECTION_PRE_PHASE_162_LEN = 3279
# The grep contract parenthetical exactly as it changed in phase 162
# (LOCKED A3): the pre-phase ``(case-insensitive)`` vs the folded one now
# embedded in ``TOOLS_SECTION``. Used to revert phase 162 for the diff pin.
_GREP_CONTRACT_PRE_PHASE_162 = "(case-insensitive)"
_GREP_CONTRACT_PHASE_162 = (
"(case- and accent-insensitive — accents fold: `besta` matches `BESTÅ`)"
)
TOOLS_SECTION_PREFIX = (
"<tools>\n"
"You may extend your context with three tools. `ls` lists the "
@@ -159,19 +185,46 @@ def test_tools_section_origin_rule_verbatim_at_its_position() -> None:
) in TOOLS_SECTION
def test_tools_section_origin_rule_is_the_only_byte_change() -> None:
"""Phase 145 (task 02) diff-style pin: the section's OTHER bytes are
byte-identical to pre-phase — the pre-phase section with ONLY the new
sentence-group inserted. Removing the rule (and the single space
that now separates it from the ``grep`` clause) reproduces the
pre-phase-145 section byte-for-byte (sha + length), and the length
delta is exactly the rule's length plus that one inserted space."""
assert len(TOOLS_SECTION) == (
TOOLS_SECTION_PRE_PHASE_145_LEN + len(ORIGIN_RULE) + 1
)
pre_phase = TOOLS_SECTION.replace(ORIGIN_RULE + " ", "")
assert len(pre_phase) == TOOLS_SECTION_PRE_PHASE_145_LEN
assert _sha256(pre_phase) == TOOLS_SECTION_PRE_PHASE_145_SHA256
def test_tools_section_search_discipline_rule_verbatim_at_its_position() -> None:
"""Phase 162 (task 03, LOCKED A4): the search-discipline rule is
LOCKED verbatim and sits at its EXACT position — immediately after
the grep sentence (the ``…retry with the plain text you expect to
see.`` clause) and BEFORE the ``For a normal search pass`` clause.
The rule + its exact boundaries are pinned as one contiguous span, so
a move or re-spelling of ANY byte fails."""
assert SEARCH_DISCIPLINE_RULE in TOOLS_SECTION
assert TOOLS_SECTION.count(SEARCH_DISCIPLINE_RULE) == 1 # exactly once
assert (
"retry with the plain text you expect to see. "
+ SEARCH_DISCIPLINE_RULE
+ " For a normal search pass only `pattern`"
) in TOOLS_SECTION
def test_tools_section_grep_fold_contract_present() -> None:
"""Phase 162 (task 03, LOCKED A3): the grep sentence now states the
FOLDED contract — the ``(case-insensitive)`` parenthetical is replaced
byte-for-byte by the folded one, and the old one is gone."""
assert _GREP_CONTRACT_PHASE_162 in TOOLS_SECTION
assert _GREP_CONTRACT_PRE_PHASE_162 not in TOOLS_SECTION
def test_tools_section_phase162_and_145_are_the_only_byte_changes() -> None:
"""Chained diff-style pin: the ONLY byte changes are phase 162's (the
folded grep contract + :data:`SEARCH_DISCIPLINE_RULE`) and phase 145's
(:data:`ORIGIN_RULE`). Reverting phase 162 (drop the rule + its
separating space, restore the pre-phase grep parenthetical) reproduces
the pre-phase-162 section byte-for-byte; reverting the origin rule on
top of that reproduces the pre-phase-145 section byte-for-byte."""
# Revert phase 162 -> pre-phase-162.
pre_162 = TOOLS_SECTION.replace(SEARCH_DISCIPLINE_RULE + " ", "")
pre_162 = pre_162.replace(_GREP_CONTRACT_PHASE_162, _GREP_CONTRACT_PRE_PHASE_162)
assert len(pre_162) == TOOLS_SECTION_PRE_PHASE_162_LEN
assert _sha256(pre_162) == TOOLS_SECTION_PRE_PHASE_162_SHA256
# Revert phase 145 -> pre-phase-145.
pre_145 = pre_162.replace(ORIGIN_RULE + " ", "")
assert len(pre_145) == TOOLS_SECTION_PRE_PHASE_145_LEN
assert _sha256(pre_145) == TOOLS_SECTION_PRE_PHASE_145_SHA256
# ---------- the LOW prompt's locked DEFLECT_MODE body ----------