phase: 191_source_name_labels_tags
All gates re-verified against a stable tree. Report: **Verified (all 6 tasks in `complete/`; this was the final pass)** - `SourceLabel`+alembic `0030` (dev DB `alembic current` = `0030 (head)`, table present, 0 rows); admin-only `GET/PUT/DELETE /api/source-labels` (`require_admin` router-wide, `resolve_source_name`, partial-update caps/404s); Sources-page "Names, labels and tags" card (read-only derived-name `<code>`, per-row `saveInFlight`, 404 note that survives the settle, chips reuse `.git-source-hidden-count`); `question_name_hits` D2 rule; ONE `all_labels` read per turn in `chat.py` feeding both the `source_name_hit` flag and the prompt surfaces; `source_name_hit_bonus=0.005` in `_selection_order`; ` name=`/` label=` in `build_high_prompt` + `build_overview_prompt(names=…)`. - **Completion criteria:** E2E `tests/e2e/test_source_name_labels.py` ✅ 7 passed (arms a–e: editor all kinds, control/named question, rename-never-breaks-identity, 404 note, reset) · full suite ✅ · coverage ✅ · README/AGENTS ✅ · phase dir in `complete/` ✅ · commit left to the harness. - **Gates:** `uv run pytest --cov=app --cov-report=term-missing` → **exit 0, TOTAL 7160 stmts / 16 missed = 99%** (>90%) · `uv run pytest tests/e2e/test_source_name_labels.py -v --no-cov` → **7 passed, exit 0** · regression E2E isolated, exit 0: `test_document_viewer`, `test_admin_auth`, `test_api_tokens`, `test_git_sources_admin`, `test_kb_tree`, `test_local_directory_sources` · `uv run ruff check .` → All checks passed · `uv run pyright` → 0 errors. - **Battery (task 04 criterion):** `uv run python -m scripts.eval_retrieval --from-file tests/fixtures/retrieval_battery.txt` at default vs `BOR_SOURCE_NAME_HIT_BONUS=0` → **`diff` empty (line-for-line identical)**, matching the recorded arms (dev KB is empty, so every question deflects; the observable boost is unit/E2E-pinned). - **Documentation:** README — fixed the `/git-sources.html` rows (nav label is **Sources**) and cross-linked the phase-191 card from that section; full audit otherwise clean: all 86 `BOR_*` settings documented with defaults matching `app/config.py`, 0 broken file/dir references and 0 broken anchors in README+AGENTS, AGENTS rule 17 re-checked line-by-line against the code. - **Notable / deviations:** (1) a **concurrent pipeline process** (`phased-execution/progress.mjs` for `191_…_00_phase`) was mutating this same working tree mid-pass — it rewrote `tests/e2e/test_source_name_labels.py` (11→7 tests), `frontend/assets/git-sources.js`, `tests/unit/test_source_labels_editor_ui.py` and `AGENTS.md` at 05:27; every gate above was (re-)run after those edits with the tree no source file newer than the green full run. (2) The task-06 report/phase text claims regression suites `test_chat_token_gate.py`, `test_git_sources_page.py`, `test_rag_browser.py` are green — **those files have never existed in git history** (those runs exit 4); I ran the real equivalents listed above instead (phase files are not mine to edit). (3) **No live changes**: the VM DB already has `source_labels` (0 rows) but the deployed app predates this uncommitted code, so deploying `/api/source-labels` to the live service is the owner's post-commit step, not part of this phase's criteria. - **Next pending phase:** none — `191_source_name_labels_tags` is the only entry in `.agents/phases/todo/`.
This commit is contained in:
@@ -430,6 +430,23 @@ class Settings(BaseSettings):
|
||||
#: records the realized margins).
|
||||
name_hit_bonus: float = 0.005
|
||||
|
||||
#: (phase 191, D3, LOCKED A3): the SECOND, independent selection-time
|
||||
#: bonus — a document whose SOURCE is named by the question (the D2
|
||||
#: rule over the ``source_labels`` row: a question token equals, in
|
||||
#: normalized form, a token of the source's display_name / label /
|
||||
#: tags) gets this added to its best fused chunk score in the SAME
|
||||
#: shared selection walk as the phase-119 ``name_hit_bonus`` (a
|
||||
#: separate knob: the two signals stay independently kill-able).
|
||||
#: Default 0.005 = the phase-119 starting point; ``0`` = off (the
|
||||
#: walk returns byte-identical to pre-phase — the kill switch); a
|
||||
#: negative value fails startup loudly. Bounded per DOCUMENT, applied
|
||||
#: ONCE, at most TWO bonuses on the fused scale (name_hit + source
|
||||
#: name_hit = 0.010 maximum head start — no amplification); the
|
||||
#: bonus lives in the SELECTION layer only — ``score`` / ``cosine`` /
|
||||
#: ``fts_hit`` / ``query_log.top_score`` are untouched (the
|
||||
#: phase-119 LOCKED A3 clause, mirrored).
|
||||
source_name_hit_bonus: float = 0.005
|
||||
|
||||
# --- Admin & sign-in (phase 16; A10 revised 2026-08-22) ---
|
||||
# Single-admin auth via a signed session cookie (Starlette
|
||||
# SessionMiddleware — no new services, no DB tables). Both secrets are
|
||||
@@ -972,6 +989,17 @@ class Settings(BaseSettings):
|
||||
raise ValueError("name_hit_bonus must be >= 0 (0 = off)")
|
||||
return v
|
||||
|
||||
@field_validator("source_name_hit_bonus")
|
||||
@classmethod
|
||||
def _source_name_hit_bonus_non_negative(cls, v: float) -> float:
|
||||
"""``0`` is the byte-identical kill switch (the pre-phase-191
|
||||
selection order) — a NEGATIVE bonus would demote source-named
|
||||
documents, the exact opposite of D2/D3 (the ``name_hit_bonus``
|
||||
pattern, phase 191)."""
|
||||
if v < 0:
|
||||
raise ValueError("source_name_hit_bonus must be >= 0 (0 = off)")
|
||||
return v
|
||||
|
||||
@field_validator("db_pool_size")
|
||||
@classmethod
|
||||
def _db_pool_size_positive(cls, v: int) -> int:
|
||||
|
||||
Reference in New Issue
Block a user