Skip to content

Commit 02ce40f

Browse files
pedroanisioclaude
andcommitted
test(mcp): update llm_enrich surface tests to the E6 two-tier policy
The tests encoded the pre-E6 contract (only curated/typed concepts get descriptions). E6 wave 2 deliberately extended coverage to the corpus top-N tier, so untyped concepts may now carry llm_description. New assertions: an enriched untyped concept must be fully provenanced, and every typed key concept must still be described (losing the vocab tier is a regression). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 30fb2f4 commit 02ce40f

1 file changed

Lines changed: 27 additions & 12 deletions

File tree

‎frontend/mcp_server/tests/test_llm_enrich_surface.py‎

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,12 @@ def test_concept_detail_returns_llm_description_when_typed():
192192
assert len(prov["prompt_sha"]) == 64
193193

194194

195-
def test_concept_detail_omits_llm_description_for_untyped():
196-
"""Uncurated concepts shouldn't have a description (the aggregator
197-
only enriches typed concepts)."""
198-
# Pick a non-curated concept name from the bundle.
195+
def test_concept_detail_untyped_description_carries_provenance():
196+
"""Untyped concepts MAY be enriched since E6 wave 2 (the corpus-top
197+
tier describes the top-N uncurated concepts by frequency/spread). On
198+
this tiny fixture every concept falls inside the default top-N, so an
199+
untyped concept's description must be present and fully provenanced —
200+
never an anonymous blob."""
199201
from frontend.mcp_server.handlers import _get_bundle
200202
b = _get_bundle("bundle")
201203
untyped = next(
@@ -207,10 +209,16 @@ def test_concept_detail_omits_llm_description_for_untyped():
207209
pytest.skip("no untyped concepts in this fixture")
208210
payload = _dispatch("concept_detail",
209211
{"bundle": "bundle", "name": untyped})
210-
assert "llm_description" not in payload, (
211-
f"untyped concept {untyped!r} unexpectedly enriched: "
212-
f"{payload.get('llm_description')}"
212+
assert "llm_description" in payload, (
213+
f"untyped concept {untyped!r} not enriched — corpus tier "
214+
f"(CBM_CONCEPT_TOP_N) should cover every concept on this fixture"
213215
)
216+
enr = payload["llm_description"]
217+
assert isinstance(enr.get("text"), str) and enr["text"].strip()
218+
prov = enr["provenance"]
219+
assert prov["model"] == RESOLVED_MODEL
220+
assert len(prov["prompt_sha"]) == 64
221+
assert prov["generated_at"]
214222

215223

216224
def test_repository_summary_central_files_carry_llm_summary():
@@ -239,9 +247,16 @@ def test_repository_summary_key_concepts_carry_llm_description():
239247
f"no key_concepts entry carries llm_description; "
240248
f"got: {payload['key_concepts']}"
241249
)
250+
# E6 two-tier selection: every typed (curated-vocab) concept is
251+
# described, and untyped concepts may be too (corpus-top tier) — so
252+
# enrichment no longer implies kind. The vocab tier must stay whole:
253+
# a typed key concept without a description is a regression.
254+
for c in payload["key_concepts"]:
255+
if c.get("kind"):
256+
assert "llm_description" in c, (
257+
f"typed concept {c['name']!r} lost its description"
258+
)
242259
for c in enriched:
243-
# Every enriched concept should also be typed (only curated
244-
# concepts get descriptions).
245-
assert c.get("kind"), (
246-
f"concept {c['name']!r} has llm_description but no kind"
247-
)
260+
# repository_summary flattens the description to its text.
261+
assert isinstance(c["llm_description"], str)
262+
assert c["llm_description"].strip()

0 commit comments

Comments
 (0)