"""Question/engine binding across actual HTTP/MCP boundaries, without an LLM.""" import asyncio import json import os import sys import pytest from test_claude_packages import backend, ROOT from packages.claude import client QUESTIONS=[ 'Čomu sa venuje diplomová práca Jána Holpa? Stručne ju predstav a uveď zdroj.', 'Porovnaj zadanie a výsledky Ondreja Megelu a Jána Holpa.\nPlán nie je výsledok; uveď zdroje.', 'Ktorí študenti majú tag "RAG" a zároveň diplomový projekt z roku 2026?'] @pytest.mark.parametrize('engine',['rag','graphrag']) def test_latest_question_and_all_conditions_cross_http_unchanged(backend,engine): for question in QUESTIONS: r=client.query_backend(question,engine,limit=7) assert r['accepted_for_delivery'] and r['query']==question and r['engine']==engine path,body,_=backend['requests'][-1] assert path=='/answer' and body['query']==question and body['engine']==engine and body['limit']==7 assert len(backend['requests'])==len(QUESTIONS) @pytest.mark.parametrize('engine',['rag','graphrag']) def test_only_a_matching_leading_command_is_removed(backend,engine): question='Aké práce má Ján Holp v roku 2020? Zachovaj výraz "RAG".' r=client.query_backend(' /'+engine.upper()+' '+question+' ',engine) assert r['accepted_for_delivery'] and r['query']==question assert backend['requests'][-1][1]['query']==question other='graphrag' if engine=='rag' else 'rag' r=client.query_backend('/'+other+' '+question,engine) assert r['reason']=='engine_mismatch' and not r['accepted_for_delivery'] assert len(backend['requests'])==1 @pytest.mark.parametrize('question',['/rag','/rag ','/graphrag']) def test_command_without_a_question_never_reaches_backend(backend,question): engine='graphrag' if question.startswith('/graphrag') else 'rag' assert client.query_backend(question,engine)['reason']=='invalid_query' assert not backend['requests'] @pytest.mark.parametrize('change',[ {'query':'A previous unrelated question','engine':'rag'}, {'query':QUESTIONS[0],'engine':'graphrag'}, ]) def test_stale_question_or_wrong_engine_cannot_deliver_another_answer(backend,change): backend['raw']=json.dumps({**backend['checked'],'answer':'OTHER_ANSWER_SHOULD_NOT_ESCAPE',**change}).encode() r=client.query_backend(QUESTIONS[0],'rag') assert r['reason']=='question_mismatch' and not r['accepted_for_delivery'] assert 'OTHER_ANSWER' not in json.dumps(r) def test_missing_question_echo_is_not_accepted(backend): backend['raw']=json.dumps({**backend['checked'],'engine':'rag'}).encode() r=client.query_backend(QUESTIONS[0],'rag') assert r['reason']=='invalid_backend_response' and not r['accepted_for_delivery'] def test_consecutive_mcp_calls_do_not_reuse_previous_queries(backend): from mcp import ClientSession,StdioServerParameters from mcp.client.stdio import stdio_client from packages.claude.mcp_server import QUESTION_POLICY async def run(): params=StdioServerParameters(command=sys.executable,args=[str(ROOT/'packages/claude/mcp_server.py')], env={**os.environ,'PYTHONDONTWRITEBYTECODE':'1'}) async with stdio_client(params) as (read,write): async with ClientSession(read,write) as session: initialized=await session.initialize() assert QUESTION_POLICY in initialized.instructions for engine,question in [('rag',QUESTIONS[0]),('graphrag',QUESTIONS[2]),('rag',QUESTIONS[1])]: result=await session.call_tool('zpwiki_'+engine,{'query':question}) assert not result.isError and result.structuredContent['query']==question assert backend['requests'][-1][1]['query']==question assert backend['requests'][-1][1]['engine']==engine asyncio.run(run())