feat(l1): advance_ai_build — record answer + generate next node
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -796,6 +796,79 @@ async def test_start_ai_build_session(test_db: AsyncSession):
|
||||
assert s.status == "active"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T8: advance_ai_build
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_advance_ai_build_appends_and_returns_next(test_db: AsyncSession, monkeypatch):
|
||||
from app.services import l1_session_service as svc
|
||||
from app.services import ai_tree_builder
|
||||
account = await _make_account(test_db)
|
||||
l1_user = await _make_user(test_db, account_id=account.id)
|
||||
s = await svc.start_ai_build_session(
|
||||
test_db, account_id=account.id, user=l1_user,
|
||||
ticket_id="t-ai", ticket_kind="internal")
|
||||
|
||||
async def fake_next(problem, category, walked):
|
||||
return {"node_type": "resolved", "id": "done", "text": "Fixed."}
|
||||
monkeypatch.setattr(ai_tree_builder, "generate_next_node", fake_next)
|
||||
|
||||
next_node = await svc.advance_ai_build(
|
||||
test_db, session_id=s.id, problem_text="printer", category="printer",
|
||||
node_id="n1", node_text="Powered on?", answer="no", note=None)
|
||||
assert next_node["node_type"] == "resolved"
|
||||
refreshed = await test_db.get(type(s), s.id)
|
||||
assert len(refreshed.walked_path) == 1
|
||||
assert refreshed.walked_path[0]["answer"] == "no"
|
||||
assert refreshed.walked_path[0]["text"] == "Powered on?"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_advance_ai_build_first_call_does_not_append(test_db: AsyncSession, monkeypatch):
|
||||
from app.services import l1_session_service as svc
|
||||
from app.services import ai_tree_builder
|
||||
account = await _make_account(test_db)
|
||||
l1_user = await _make_user(test_db, account_id=account.id)
|
||||
s = await svc.start_ai_build_session(
|
||||
test_db, account_id=account.id, user=l1_user,
|
||||
ticket_id="t-ai-first", ticket_kind="internal")
|
||||
|
||||
async def fake_next(problem, category, walked):
|
||||
return {"node_type": "question", "id": "q1", "text": "Is it plugged in?"}
|
||||
monkeypatch.setattr(ai_tree_builder, "generate_next_node", fake_next)
|
||||
|
||||
# First call: node_id=None — nothing should be appended
|
||||
next_node = await svc.advance_ai_build(
|
||||
test_db, session_id=s.id, problem_text="printer", category="printer",
|
||||
node_id=None)
|
||||
assert next_node["node_type"] == "question"
|
||||
assert next_node["id"] == "q1"
|
||||
refreshed = await test_db.get(type(s), s.id)
|
||||
assert len(refreshed.walked_path) == 0
|
||||
assert refreshed.current_node_id == "q1"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_advance_ai_build_wrong_session_kind_raises(test_db: AsyncSession, monkeypatch):
|
||||
from app.services import l1_session_service as svc
|
||||
from app.services import ai_tree_builder
|
||||
account = await _make_account(test_db)
|
||||
l1_user = await _make_user(test_db, account_id=account.id)
|
||||
# start an adhoc session (not ai_build)
|
||||
s = await svc.start_adhoc_session(
|
||||
test_db, account_id=account.id, user=l1_user,
|
||||
ticket_id="t-adhoc-guard", ticket_kind="internal")
|
||||
|
||||
async def fake_next(problem, category, walked): # pragma: no cover
|
||||
return {"node_type": "question", "id": "q1", "text": "?"}
|
||||
monkeypatch.setattr(ai_tree_builder, "generate_next_node", fake_next)
|
||||
|
||||
with pytest.raises(ValueError, match="ai_build"):
|
||||
await svc.advance_ai_build(
|
||||
test_db, session_id=s.id, problem_text="printer", category="printer")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# T14 audit log tests (spec §5.6.1)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user