Files
FabledScribe/tests/test_retrieval_miss_route.py
T
bvandeusenandClaude Opus 5.5 ff08500128
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 15s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m10s
CI & Build / Build & push image (push) Canceled after 0s
CI & Build / Python tests (push) Canceled after 1m23s
docs(6209): wide net, startup, stamps, slippage, miss route and parity tests
Eight more test files state the property they pin as a present-tense
fact. Incident narratives (a dated storage stall, a week of zero tuning
events, a two-project poisoned ledger, a twenty-site owner audit) become
the failure shape each test defends; one-install figures that name a rule
become a general worked example with the calibration numbers kept. The
family-grouping regression guard is renamed for what it checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:27:17 -04:00

153 lines
6.5 KiB
Python

"""A recognized retrieval miss has a route, and the route is ordered.
WHY THIS EXISTS
The tuning loop is three tools — `retrieval_surfaces` to read a dial,
`tune_retrieval` to move one with its argument attached,
`migrate_retrieval_floor` to carry it across a model change — and the model is
meant to be the one using them most of the time. A tool classified in
`server.py`'s read/write lists and named on no instruction surface is never
called: nothing a session reads tells it the tool exists.
So this file guards a ROUTE, not a behaviour: that a session which notices a
rule missed the moment it governed has somewhere written down to take it.
WHY THE ORDER IS THE LOAD-BEARING PART
`test_the_record_comes_before_the_dial` is the test that matters here, and it is
positional on purpose. Both halves of the route are individually reasonable —
read the telemetry, move the floor — and stated in either order they read as a
menu. They are not a menu. A rule's `when_to_apply` IS the text its score is
computed against, so a miss is evidence about that text first; a floor is one
number governing every record on the surface and cannot tell a badly-worded
trigger from a genuinely distant one.
Which is why the order is asserted rather than suggested: a rule can score
0.65 and rank fifth for the moment it governs, behind rules that RESTRAIN the
same act. Every percentile says "lower the floor" — and at 0.60 the arm
delivers those restraints and still not that rule, while rewriting its trigger
to lead with the symptom puts it first at 0.71. The dial-first path can be
available, statistically supported, and wrong.
"""
from __future__ import annotations
import pathlib
import re
ROOT = pathlib.Path(__file__).resolve().parents[1]
# The three tools that shipped with no route to them. Named together because
# the gap was all three at once, and a partial fix would leave the loop broken
# at whichever step lost its pointer.
TUNING_TOOLS = ("retrieval_telemetry", "update_rule", "retrieval_surfaces",
"tune_retrieval")
def _skill() -> str:
# The route lives in missed-retrieval.md, a reference file of using-scribe;
# the skill is SKILL.md and its references read together.
from tests.helpers import skill_text
return skill_text("using-scribe")
def _instructions() -> str:
src = (ROOT / "src/scribe/mcp/server.py").read_text()
match = re.search(r'_INSTRUCTIONS = """(.*?)"""', src, re.S)
assert match, "server.py no longer defines _INSTRUCTIONS as a literal"
return match.group(1)
def test_the_route_names_every_tool_it_depends_on():
"""The measured gap: machinery with no instruction surface pointing at it."""
text = _skill()
missing = [t for t in TUNING_TOOLS if t not in text]
assert not missing, (
f"using-scribe no longer names {missing}. These tools reach a session "
f"through this skill and nowhere else — when they were named on no "
f"surface at all, the tuning loop logged zero events in its lifetime."
)
def test_the_record_comes_before_the_dial():
"""THE GUARD. Stated in the wrong order, the route becomes a menu.
Positional rather than a presence check, because presence is exactly what
a reordering preserves. Asserted on first occurrence: what a reader meets
first is what they act on.
"""
text = _skill()
read_records = text.index("retrieval_telemetry")
fix_trigger = text.index("update_rule(when_to_apply")
move_dial = text.index("tune_retrieval")
assert read_records < move_dial, (
"the route reaches tune_retrieval before retrieval_telemetry. Reading "
"the refused records is the step that separates a real miss from a bar "
"doing its job — a percentile cannot, and has been measured pointing "
"the wrong way."
)
assert fix_trigger < move_dial, (
"the route reaches tune_retrieval before update_rule. A miss is "
"evidence about the trigger first: rewording one trigger changes one "
"rule's reach, while moving a floor changes every record on the surface."
)
def test_the_route_says_what_a_floor_costs_that_a_trigger_does_not():
"""The REASON for the order, not just the order.
Without it the ordering is arbitrary and the first session under deadline
will invert it. The asymmetry is the whole argument: one trigger against
every record on the surface.
"""
text = " ".join(_skill().split()).lower()
assert "take it to the record first and the dial second" in text
assert "changes one rule's reach" in text
assert "changes what every record on" in text
def test_a_session_can_notice_its_own_miss():
"""Both noticers, or the route only ever fires when the operator complains.
The self-noticed case is the one that scales — it does not need somebody
watching — and it is the one a surface written only around operator
feedback silently omits.
"""
text = " ".join(_skill().split()).lower()
assert "either noticer" in text
assert "reached for a rule nobody offered you" in text
# Both directions too: a rule that never arrives and one that always does
# are the same misjudgment, and they point at different dials.
assert "either direction counts" in text
def test_writing_a_new_record_asks_what_already_covers_the_moment():
"""The create path is retrieval-affecting, and nothing said so.
A second record on one moment splits a single budget between two claims,
and when the copies differ in force the softer one teaches a session that
binding guidance is optional. `what_might_apply` rather than `search`
because a bar is exactly what lets the existing record hide.
"""
text = " ".join(_skill().split()).lower()
assert "ask what already covers that moment" in text
assert "what_might_apply" in text
assert "no bar" in text
def test_the_route_stays_off_the_index():
"""`_INSTRUCTIONS` is the only surface every MCP client gets.
It carries no pointer to this route, because the index is not a rulebook:
a missed rule is noticed mid-work, not at session start, and the spec asks server instructions for the
workflow across tools, not stance. using-scribe states the route (the tests
above pin it); the index keeps what_might_apply, the tool that opens it.
Whitespace-flattened before matching: the block is hard-wrapped, so a
phrase straddles a line break the moment anything before it changes
length.
"""
text = " ".join(_instructions().split()).lower()
assert "what_might_apply" in text
assert "take it to the record first" not in text