Cross-language prior-art labelling + close the surfaced→pulled loop on get_task #87
@@ -27,6 +27,7 @@ from scribe.services import rulebooks as rulebooks_svc
|
||||
from scribe.services import systems as systems_svc
|
||||
from scribe.services import task_logs as task_logs_svc
|
||||
from scribe.services import trash as trash_svc
|
||||
from scribe.services.note_usage import record_pulled
|
||||
|
||||
|
||||
async def list_tasks(
|
||||
@@ -99,6 +100,14 @@ async def get_task(task_id: int) -> dict:
|
||||
data["suppressed_rules"] = applicable.get("suppressed_rules", [])
|
||||
data["suppressed_topics"] = applicable.get("suppressed_topics", [])
|
||||
data.update(await access_svc.describe_provenance(uid, note))
|
||||
# Same reasoning as get_note's record_pulled, and this is the tool where it
|
||||
# matters MOST: auto-inject ranks kind-blind over a corpus that is
|
||||
# overwhelmingly tasks and issues, so tasks dominate what it surfaces. Without
|
||||
# this the surfaced→pulled loop was open exactly where the volume is — every
|
||||
# surfaced task counted as never-pulled because the tool that opens one didn't
|
||||
# say so, driving auto-inject's measured pull-through toward zero for its own
|
||||
# dominant kind. #1038 and #2085 are explicitly gated on that number (#2245).
|
||||
record_pulled(user_id=uid, note_id=int(note.id), source="mcp_get_task")
|
||||
return data
|
||||
|
||||
|
||||
|
||||
@@ -186,3 +186,37 @@ async def test_auto_inject_records_what_survived_the_margin_gate():
|
||||
|
||||
assert surfaced.call_args.kwargs["note_ids"] == [1]
|
||||
assert surfaced.call_args.kwargs["source"] == "auto_inject"
|
||||
|
||||
|
||||
def test_every_getter_that_can_be_surfaced_also_records_a_pull():
|
||||
"""Rule #33 contract check — and the one that would have caught #2245.
|
||||
|
||||
`surfaced` and `pulled` only mean something as a PAIR: the rate between them
|
||||
is what #1038 and #2085 gate on. That pair is only closed if the tool which
|
||||
OPENS a record reports it. `get_note` did, `get_snippet` did, `get_task` did
|
||||
NOT — and auto-inject ranks kind-blind over a corpus that is overwhelmingly
|
||||
tasks and issues, so the gap sat exactly where the volume is: every surfaced
|
||||
task counted as never-pulled, dragging measured pull-through toward zero for
|
||||
the menu's own dominant kind.
|
||||
|
||||
Asserted by source inspection rather than by calling the tools, because the
|
||||
failure is a MISSING call — which no behavioural test of the tool's return
|
||||
value can see.
|
||||
"""
|
||||
import inspect
|
||||
|
||||
from scribe.mcp.tools import notes as notes_tools
|
||||
from scribe.mcp.tools import snippets as snippet_tools
|
||||
from scribe.mcp.tools import tasks as task_tools
|
||||
|
||||
getters = (
|
||||
(notes_tools, "get_note"),
|
||||
(task_tools, "get_task"),
|
||||
(snippet_tools, "get_snippet"),
|
||||
)
|
||||
for module, name in getters:
|
||||
src = inspect.getsource(getattr(module, name))
|
||||
assert "record_pulled(" in src, (
|
||||
f"{name} can be surfaced in an auto-inject menu but records no pull — "
|
||||
"its pull-through rate will read as zero regardless of real usage"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user