Files

120 lines
4.8 KiB
Python

"""Every goal surface applies the same commands to real persisted state."""
import asyncio
import os
import queue
from types import SimpleNamespace
import pytest
from hermes_cli import goals
def _surface(surface, mgr, monkeypatch, prompts=None):
prompts = prompts if prompts is not None else []
if surface == "cli":
from hermes_cli.cli_commands_mixin import CLICommandsMixin
cli = object.__new__(CLICommandsMixin)
cli._get_goal_manager = lambda: mgr
cli._pending_input = queue.Queue()
cli.conversation_history = []
def execute(arg):
cli._handle_goal_command('/goal ' + arg)
while not cli._pending_input.empty():
prompts.append(cli._pending_input.get_nowait())
return execute
if surface == "gateway":
from gateway.run_busy import GatewayBusySessionMixin
from gateway.slash_commands_goals import GatewayGoalCommandsMixin
class Runner(GatewayBusySessionMixin, GatewayGoalCommandsMixin):
pass
runner = object.__new__(Runner)
async def manager(event):
return mgr, None
async def execute(fn, *args):
return fn(*args)
runner._get_goal_manager_for_event = manager
runner._run_in_executor_with_context = execute
runner._adapter_and_key_for = lambda event: (None, None)
runner._enqueue_goal_turn = lambda event, text, **kwargs: prompts.append(text)
runner._resume_caller_is_admin = lambda source: True
def execute(arg):
event = SimpleNamespace(get_command_args=lambda: arg, source=None)
if arg == 'show':
return asyncio.run(runner._busy_goal_command(event, mgr.session_id, None))
return asyncio.run(runner._handle_goal_command(event))
return execute
from tui_gateway import server
server._sessions[mgr.session_id] = {'session_key': mgr.session_id}
def execute(arg):
result = server._methods['command.dispatch'](1, {
'session_id': mgr.session_id, 'name': 'goal', 'arg': arg})
if result.get('result', {}).get('type') == 'send':
prompts.append(result['result']['message'])
return result
return execute
@pytest.mark.parametrize('surface', ['cli', 'gateway', 'tui'])
@pytest.mark.parametrize('command', [
'show', 'draft', 'draft build it', 'drafting docs', 'wait', 'wait nope',
'wait {pid} build', 'unwait', 'gate add true', 'gate remove 1',
'gate clear', 'gate list', 'pause', 'resume', 'clear', 'stop', 'done',
'build it\nverify: test passes', 'status', '',
])
def test_surface_goal_state_matches_cli(surface, command, monkeypatch):
monkeypatch.setattr(goals, 'draft_contract', lambda objective: goals.GoalContract())
goals._DB_CACHE.clear()
command = command.format(pid=os.getpid())
snapshots = []
for name in ('cli', surface):
mgr = goals.GoalManager(session_id=name + '-parity-' + surface)
mgr.set('original objective')
mgr.add_gate('original gate')
mgr.wait_on(os.getpid(), reason='existing barrier')
result = _surface(name, mgr, monkeypatch)(command)
if name == 'gateway' and command == 'show':
assert mgr.state.goal in result
state = goals.load_goal(mgr.session_id)
if state:
from dataclasses import asdict
state = asdict(state)
for key in ('created_at', 'updated_at', 'waiting_since'):
state.pop(key, None)
snapshots.append(state)
assert snapshots[0] == snapshots[1]
@pytest.mark.parametrize('surface', ['cli', 'gateway', 'tui'])
@pytest.mark.parametrize('draft_result', ['contract', 'unavailable', 'error'])
def test_drafts_start_work_but_inspection_and_literal_prefixes_do_not_draft(
surface, draft_result, monkeypatch,
):
calls = []
def draft(objective):
calls.append(objective)
if draft_result == 'error':
raise RuntimeError('aux offline')
return goals.GoalContract(verification='tests pass') if draft_result == 'contract' else None
monkeypatch.setattr(goals, 'draft_contract', draft)
goals._DB_CACHE.clear()
mgr = goals.GoalManager(session_id='draft-' + surface)
prompts = []
execute = _surface(surface, mgr, monkeypatch, prompts)
execute('draft build it')
state = goals.load_goal(mgr.session_id)
assert state.goal == 'build it'
assert state.has_contract() == (draft_result == 'contract')
assert calls == ['build it']
assert prompts == ['build it']
execute('show')
execute('draft')
execute('wait invalid')
assert goals.load_goal(mgr.session_id).goal == 'build it'
assert prompts == ['build it']
execute('drafting docs')
assert goals.load_goal(mgr.session_id).goal == 'drafting docs'
assert calls == ['build it']
assert prompts[-1] == 'drafting docs'