Rules become findable: canon catalog, triggers, tiers, edges, retrieval, surfacing (milestone 307, steps 1–5) #131

Merged
bvandeusen merged 13 commits from dev into main 2026-08-26 17:12:40 -04:00
Showing only changes of commit 879ef3053e - Show all commits
+28
View File
@@ -113,6 +113,15 @@ async def test_untagged_hint_escalates_in_a_mature_zero_systems_project():
patch("scribe.mcp.tools.systems.notes_svc") as notes:
svc.list_systems = AsyncMock(return_value=[])
notes.list_notes = AsyncMock(return_value=(recent, 282))
# The standard names come from the GLOBAL catalog now (milestone 307),
# not a module constant — so the ask reads them through the service.
# That the SEEDED vocabulary is these eight is migration 0087's
# business, asserted against a real database in the inception
# integration test; what belongs here is that whatever the catalog
# holds reaches the ask verbatim.
svc.standard_systems = AsyncMock(return_value=[
("CI & Release", "..."), ("Auth & Access", "..."),
])
hint = await untagged_systems_hint(1, 5)
assert "282 records" in hint
assert "Fix scrape retry backoff" in hint # the project's own evidence
@@ -126,6 +135,25 @@ async def test_untagged_hint_escalates_in_a_mature_zero_systems_project():
assert "no Systems yet" not in hint
@pytest.mark.asyncio
async def test_bootstrap_ask_still_asks_when_the_catalog_is_unreachable():
"""The standard names are an AID to the question, not the question. If the
catalog read fails (or an install has an empty one), the ask must still
carry the project's evidence and demand the same deliverable — degrading to
a weaker nudge is acceptable, going silent is not."""
from scribe.mcp.tools.systems import untagged_systems_hint
recent = [fake_note(title="Fix scrape retry backoff")]
with patch("scribe.mcp.tools.systems.systems_svc") as svc, \
patch("scribe.mcp.tools.systems.notes_svc") as notes:
svc.list_systems = AsyncMock(return_value=[])
notes.list_notes = AsyncMock(return_value=(recent, 282))
svc.standard_systems = AsyncMock(side_effect=RuntimeError("db down"))
hint = await untagged_systems_hint(1, 5)
assert hint is not None
assert "282 records" in hint and "create_system" in hint
assert "3-6" in hint and "without asking permission" in hint
@pytest.mark.asyncio
async def test_bootstrap_ask_stays_quiet_below_threshold_and_fails_open():
from scribe.mcp.tools import systems as tools