Files
nisse/tests/integration/test_planning_live.py
T
dongarandClaude Opus 5.5 3cf4cefacd Rename the delegate and consultant roles to helper and expert
Architecture L9's role names, for the two roles with a direct
counterpart: the delegation role is now 'helper' and the ask_expert role
'expert', in RoleMap, configuration (roles.helper, roles.expert),
recorded events and tests. 'planner' and 'executor' stay distinct for
now; they become 'driver' when the new loop merges them (Development
Plan M2.3).

Configurations must rename their keys: nisse-dev.example.yaml and
tests/integration/nisse-test.yaml are updated here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
2026-10-01 23:04:37 +00:00

48 lines
1.6 KiB
Python

"""Live planning turn: a real model must answer with a submit_plan or
ask_human tool call, not prose.
Plans with the test config's planner role. The planner role is a frontier
model today (Development Plan §2), and small local models do not hold the tool-call
contract reliably, so that role must be one that does.
"""
import io
from pathlib import Path
import pytest
from nisse_dev.canonical import UserMessage
from nisse_dev.control import AskHuman, SubmitPlan
from nisse_dev.llm import LiteLLMClient, RoleMap
from nisse_dev.oplog import OpLog
from nisse_dev.planner import LLMPlanningAgent
from nisse_dev.state import StateStore
pytestmark = pytest.mark.integration
def test_live_planning_turn_returns_a_tool_action(
tmp_path: Path, litellm: LiteLLMClient, live_model: str
) -> None:
model = live_model
roles = RoleMap(executor=model, planner=model, helper=model, expert=model)
store = StateStore(tmp_path / "state.db", oplog=OpLog("nisse-dev", io.StringIO()))
store.append_event(
UserMessage(
text=(
"Project 'hello-cli': a Python script that prints a greeting. "
"Draft the architecture plan."
),
source="live-test",
)
)
agent = LLMPlanningAgent(litellm, store, roles)
action = agent.plan("arch", "hello-cli")
assert isinstance(action, SubmitPlan | AskHuman)
text = action.content if isinstance(action, SubmitPlan) else action.question
assert text.strip(), "tool call carried empty content"
# The turn must be durable regardless of what the model said (L8/L7).
assert len(store.read_events()) > 1