Queue clear — shared ACL on lists, semantic q, full telemetry ledger, --color-* retired #103
@@ -36,22 +36,24 @@ async def search_route():
|
||||
content_type = request.args.get("content_type", "all")
|
||||
limit = min(request.args.get("limit", 10, type=int), 50)
|
||||
is_task = _content_type_to_is_task(content_type)
|
||||
# Same association filter the MCP tool takes (#33). The project filter this
|
||||
# route is still missing is #2463's — it carries a default-scope UI decision
|
||||
# this change must not preempt.
|
||||
# Same association filters the MCP tool takes (#33). Optional, default
|
||||
# global: this route has NO frontend consumer today (measured 2026-08-08 —
|
||||
# the web UI searches through /api/knowledge), so it serves API callers,
|
||||
# and an API caller states its scope explicitly.
|
||||
system_id = request.args.get("system_id", type=int)
|
||||
project_id = request.args.get("project_id", type=int)
|
||||
|
||||
t0 = time.perf_counter()
|
||||
results = await semantic_search_notes(
|
||||
uid, q, limit=limit, is_task=is_task, threshold=_REST_SEARCH_THRESHOLD,
|
||||
system_id=system_id,
|
||||
project_id=project_id, system_id=system_id,
|
||||
# The user typed this, so it reaches everything they may read.
|
||||
scope="read",
|
||||
)
|
||||
record_retrieval(
|
||||
user_id=uid, source="rest_search", query=q,
|
||||
threshold=_REST_SEARCH_THRESHOLD, limit=limit,
|
||||
project_id=None, is_task=is_task, results=results,
|
||||
project_id=project_id, is_task=is_task, results=results,
|
||||
duration_ms=(time.perf_counter() - t0) * 1000.0,
|
||||
)
|
||||
owners = await owner_names_for(
|
||||
|
||||
@@ -401,6 +401,8 @@ async def _semantic_knowledge_search(
|
||||
semantic_search_notes,
|
||||
)
|
||||
is_task_filter = True if note_type in ("task", "plan") else (False if note_type else None)
|
||||
import time as _time
|
||||
_t0 = _time.perf_counter()
|
||||
candidates = await semantic_search_notes(
|
||||
user_id=user_id,
|
||||
scope="read",
|
||||
@@ -413,6 +415,18 @@ async def _semantic_knowledge_search(
|
||||
is_task=is_task_filter,
|
||||
project_id=project_id,
|
||||
)
|
||||
# The human's MAIN search surface, and it logged nothing — so
|
||||
# retrieval_logs claimed the web's search was /api/search, a narrower
|
||||
# path with (measured) zero frontend consumers. Distinct source, so
|
||||
# threshold tuning can include or exclude human queries deliberately
|
||||
# rather than by accident (#2463).
|
||||
from scribe.services.retrieval_telemetry import record_retrieval
|
||||
record_retrieval(
|
||||
user_id=user_id, source="browse_search", query=q,
|
||||
threshold=INTERACTIVE_SEARCH_THRESHOLD, limit=min(200, limit * 4),
|
||||
project_id=project_id, is_task=is_task_filter, results=candidates,
|
||||
duration_ms=(_time.perf_counter() - _t0) * 1000.0,
|
||||
)
|
||||
for _score, note in candidates:
|
||||
if note.deleted_at is not None:
|
||||
continue
|
||||
|
||||
@@ -326,6 +326,7 @@ async def _reserve_slot_for_reuse(
|
||||
return kept # reuse already represented; nothing to do
|
||||
|
||||
top_k = cfg["top_k"]
|
||||
_t0 = time.perf_counter()
|
||||
reuse = await semantic_search_notes(
|
||||
user_id, query,
|
||||
limit=1,
|
||||
@@ -335,6 +336,17 @@ async def _reserve_slot_for_reuse(
|
||||
note_type=_REUSE_KINDS,
|
||||
scope="browse",
|
||||
)
|
||||
# A real semantic query competing for a menu slot — logged like the scored
|
||||
# arm it displaces. Before this, the hit it PUSHED OUT was in
|
||||
# retrieval_logs and the query that pushed it out was not, so the slot
|
||||
# could never be evaluated against what it replaced (#2463; #1038 and
|
||||
# #2085 are gated on this ledger being complete).
|
||||
record_retrieval(
|
||||
user_id=user_id, source="reuse_slot", query=query,
|
||||
threshold=cfg["threshold"], limit=1, project_id=project_id,
|
||||
is_task=None, results=reuse,
|
||||
duration_ms=(time.perf_counter() - _t0) * 1000.0,
|
||||
)
|
||||
# Verify the kind rather than trusting the query that asked for it, and
|
||||
# dedup on top of exclude_ids. This slot exists FOR reuse kinds — a slot
|
||||
# silently spent on something else is worse than no slot, because the line
|
||||
|
||||
Reference in New Issue
Block a user