All verification complete. Final report: **Phase 142 final verification pass — all green** - **Verified implemented** (working tree matches design; app diff is exactly 2 lines of logic): `app/rag/overview.py` — `regenerate_overview` now orders the lite-model document list `created_at` desc, `(source, path)` tie-break (newest docs survive the cap); `app/rag/prompts.py` — `_KB_INTRO` rewritten to the honest intro (recency bias, "map not inventory", verify-with-`ls`/`grep`; "(generated at import time)" gone). - **Completion criteria:** 1. Forced-cap outline leads with newest docs — ✅ E2E `test_kb_overview_freshness.py` test 1 (cap 300, digest from `zz_new/z.md`, no "old" tokens) + integration repro (cap 150 → `mydocs zz new 03 md zz new 03`) 2. New honest intro served in `<knowledge_base>` — ✅ unit pin (verbatim) + E2E test 2 (`build_kb_section` surface, tag/cap byte-stable) 3. Gates — ✅ `uv run pytest --cov=app --cov-report=term-missing`: **3359 passed**, `app/` TOTAL **99%** (>90%); `uv run pytest tests/e2e/test_kb_overview_freshness.py -v --no-cov`: **3 passed** in isolation; `uv run pytest tests/e2e/test_kb_overview.py -v --no-cov`: **4 passed** in isolation; `uv run ruff check . && uv run pyright`: **clean, 0 errors** 4. No behavior change in completed phases — ✅ cap env knob, change-gated sync trigger, `build_kb_section` cap/marker, deflect path all byte-identical (pinned pins pass in the 3359) - **Documentation:** README.md reviewed in full (every `.env.example` var documented with matching defaults, all endpoints/routes verified against `app/api/`, Quick Start/deploy/troubleshooting claims verified) and AGENTS.md re-reviewed (rules + quick reference accurate) — **verified consistent, no changes needed**. - **Decisions:** none required — no defects found; no live-infra changes (only the already-running local `db` container was used by tests). - **Next pending phase:** `.agents/phases/todo/143_mobile_keyboard_after_answer`.
7.8 KiB
Phase 142 — the KB overview stays fresh: newest documents survive the cap, and the model is told the outline is partial
Source: TODO.md L4 — "The agent is really struggling with questions like 'Summarize the last 10 phases of brain of Reese'. When I asked that to the current deployment it said 'I'll pull the details for the last 10 phases (104–113).' when it clearly had phase 137 loaded in the RAG… 'The <knowledge_base> section in the system prompt only generated summaries up to phase 113 at import time. The phases 128–137 exist as full markdown files… but their summaries weren't included in the initial KB index. This is a KB sync/generation gap, not a retrieval logic bug.'"
Story: n/a (TODO-derived phase, Protocol B append).
Context: app/rag/overview.py — regenerate_overview (the document-list query order_by(Document.source, Document.path) ~L232, best-effort change-gated per the module docstring), build_overview_prompt (one line per doc source — path — title — {first summary line}, capped at max_chars with the shared TRUNCATION_MARKER), load_kb_overview; app/config.py L216 — overview_input_max_chars (BOR_OVERVIEW_INPUT_MAX_CHARS, default 40 000); app/rag/prompts.py — _KB_INTRO (L128–132: literally says "(generated at import time)") and build_kb_section (L399+); app/api/sync.py ~L590 — the overview regeneration gate (summary.added + summary.updated > 0 — the sync IS change-gated correctly; the staleness is inside the generation, not the trigger); tests/e2e/test_kb_overview.py (the mock's KB_OVERVIEW_MODE digest = first 8 tokens of the document list — ORDER-DEPENDENT, must be re-pinned), tests/integration/test_import_docs_overview.py (the import-time trigger), app/models.py — Document.created_at (L123 — the DOCUMENT's date, phase 106: git-history/mtime-derived and owner-correctable, the same date the read result's date: line shows — the "when is this document from" signal, exactly what "the last N …" means). Root cause (traced): on the owner's 1 000-doc KB the document list is ≈100k+ chars; the 40k cap cuts a LEXICOGRAPHIC prefix (order_by (source, path) — "113_…" sorts before "128_…", and "131_…"–"140_" sort after "13_…"), so the newest phases never reach the lite model and the stored outline confidently describes a KB that ends mid-11x; the model then anchors "the last 10 phases" on that stale image.
Locked (owner-confirmed 2026-09-30, chat): recency ordering (newest documents first so they survive the cap; the cap itself is unchanged) + the honest <knowledge_base> intro (drops "(generated at import time)"; tells the model the outline is compact/possibly partial and to verify "latest/complete" questions with ls/grep first). No map-reduce rewrite this phase.
Objective
"Summarize the last 10 phases" stops being a guess: the overview's input is ordered newest-first so recent documents are the ones the outline covers when the cap bites, and the <knowledge_base> intro stops teaching the model that a partial outline is the whole KB — it now says the outline is a possibly-partial picture and points at ls/grep for "what's the latest / the complete set" questions.
Dependencies
141_read_range_dedupe_fix(todo) — pipeline order only; no code dependency.
Design (shared by all tasks — the executor reads this, not the chat)
- Ordering (task 02):
regenerate_overview's query becomesorder_by(Document.created_at.desc(), Document.source, Document.path)— newest documents FIRST (created_atis the document's date per phase 106 — the same date thedate:line in a read result shows; the owner's phase-128–137 files carry newer git dates than the 113-era files, so they lead the list and survive the cap). The (source, path) secondary keys keep the tie-break deterministic for same-date docs (the common case within one commit/import — those fall back to the old lexicographic order, so same-date fixtures stay byte-identical). The cap (BOR_OVERVIEW_INPUT_MAX_CHARS, default 40 000) and the cap's cut+TRUNCATION_MARKERbehavior are UNCHANGED (house truncation convention; the env knob stays the owner's lever). Zero other call-site changes: the sync's change-gate (task-31/32 trigger) already regenerates whenever the KB changes — the staleness was purely inside the list. - Intro (task 03):
_KB_INTROrewritten (it is a prompt constant — PLAN §4's convention: persona/prompt text changes ship with the phase's prompt tests; the<knowledge_base>TAG and the section's cap behavior inbuild_kb_sectionstay byte-stable): the outline is a COMPACT, possibly partial picture of the KB that favors RECENT documents — and for questions about the latest state or the complete set ("the last N …", "everything about …"), verify withls(drill down) /grepbefore answering from the outline. One short paragraph, same tone asSUGGEST_INTRO(L152). - Repro (task 01): before any fix, a failing test proves the traced root cause:
build_overview_promptgiven a doc list whose joined lines exceedmax_charskeeps the lexicographic FIRST lines and drops the last; and (integration) a KB where the newest docs' paths sort lexicographically LAST is regenerated with the pre-fix ordering → the stored outline (the mock's 8-token digest) names the OLD docs, not the new ones. The repro is written against the CURRENT code (red), then tasks 02/03 flip it green. - E2E (task 04): dedicated file — a fixture KB whose document count × line length exceeds a FORCED small cap (
BOR_OVERVIEW_INPUT_MAX_CHARSset low via the E2E settings fixture) → regenerate through the mock → the stored outline's digest tokens come from the NEWEST document (recency ordering visible end-to-end through the real prompt path), and the served chat prompt's<knowledge_base>section carries the NEW intro copy (asserted from the echo path or the direct prompt-build surface — the phase-31 E2E already exposes the section to the UI via the first-bullet echo).
Tasks
01_cap_ordering_repro.md— the red repro tests (unit: cap keeps the lexicographic prefix; integration: newest-sorting-last docs missing from the regenerated outline).02_recency_ordering.md— thecreated_at.desc()ordering + the order-dependent digest re-pins.03_honest_kb_intro.md— the_KB_INTROrewrite + the prompt tests.04_e2e_outline_freshness.md— the dedicated E2E (forced cap → newest doc in the outline; the new intro served).
Testing & Quality
- Unit:
build_overview_promptcap behavior unchanged (the cut + marker, the pathological budget); the new ordering (regeneration with mixedcreated_atdocs → newest first; same-date tie-break by (source, path)); the intro copy pin. - Integration: the import-time trigger still regenerates exactly on KB change (the pre-existing
tests/integration/test_import_docs_overview.pygreen); the repro flipped green. - E2E: one dedicated Playwright file, run in isolation, mock-only;
tests/e2e/test_kb_overview.py(phase 31) green with re-pinned digest. - Coverage: >90% on new/modified code (
app/).
Completion Criteria
- with the cap forced, the regenerated outline is built from the NEWEST documents (the 1 000-doc "ends at phase 113" failure mode is gone: the newest sort-last docs are the ones represented)
- the served
<knowledge_base>section carries the new honest intro (no "(generated at import time)"; the verify-with-ls/grepteaching present) uv run pytest --cov=app --cov-report=term-missinggreen,app/coverage >90%;uv run pytest tests/e2e/test_kb_overview_freshness.py -v --no-covgreen in isolation;tests/e2e/test_kb_overview.pystill green in isolation;uv run ruff check . && uv run pyrightclean- no behavior change in completed phases (the cap env knob, the change-gated trigger, the
build_kb_sectioncap/marker behavior, the deflect path)