Files
oh-my-pi/python/robomp/tests/test_persona.py
T
can1357 2c773a12a4 Add 'python/robomp/' from commit '553fd1cfcf59e4c501c54fc81bc083ffd2ca007b'
git-subtree-dir: python/robomp
git-subtree-mainline: 4f6e70f779
git-subtree-split: 553fd1cfcf
2026-05-16 21:00:42 +02:00

133 lines
4.2 KiB
Python

"""Coverage for the directive prompt assembly."""
from __future__ import annotations
from dataclasses import dataclass
from robomp import persona
from robomp.worker import DirectiveInfo, ThreadMessage
@dataclass(slots=True, frozen=True)
class _Repo:
full_name: str = "octo/widget"
default_branch: str = "main"
clone_url: str = ""
private: bool = False
@dataclass(slots=True, frozen=True)
class _Issue:
repo: str = "octo/widget"
number: int = 1080
title: str = "broken thing"
body: str = "the body text"
state: str = "open"
author: str = "alice"
labels: tuple[str, ...] = ()
is_pull_request: bool = False
@dataclass(slots=True, frozen=True)
class _Workspace:
branch: str = "farm/abc/test"
session_dir: str = "/tmp/session"
context_dir: str = "/tmp/ctx"
repo_dir: str = "/tmp/repo"
@dataclass(slots=True, frozen=True)
class _Comment:
id: int = 1
author: str = "can1357"
body: str = "@roboomp please fix"
created_at: str = "2026-05-14T20:00:00Z"
def test_render_thread_empty_yields_placeholder() -> None:
assert persona._render_thread(()).startswith("(no prior")
def test_render_thread_orders_kinds_with_appropriate_headers() -> None:
thread = (
ThreadMessage(kind="issue_body", author="alice", body="orig report", created_at=""),
ThreadMessage(kind="comment", author="bob", body="me too", created_at="2026-05-01T10:00:00Z"),
ThreadMessage(
kind="review_comment",
author="codex",
body="leak here",
created_at="2026-05-02T10:00:00Z",
path="src/foo.py",
line=42,
),
ThreadMessage(
kind="review",
author="codex",
body="two issues",
created_at="2026-05-02T10:01:00Z",
state="CHANGES_REQUESTED",
),
)
out = persona._render_thread(thread)
# Issue body header (no timestamp).
assert "### @alice — issue body" in out
assert "orig report" in out
# Comment header with timestamp.
assert "### @bob — comment *(2026-05-01T10:00:00Z)*" in out
assert "me too" in out
# Review comment with file:line anchor.
assert "### @codex — review comment on `src/foo.py`:L42" in out
assert "leak here" in out
# Review with state badge.
assert "### @codex — review (CHANGES_REQUESTED)" in out
assert "two issues" in out
def test_directive_prompt_embeds_thread_and_directive_body() -> None:
thread = (
ThreadMessage(kind="comment", author="alice", body="follow up please", created_at="2026-05-01T10:00:00Z"),
)
out = persona.directive(
repo=_Repo(),
issue=_Issue(),
comment=_Comment(),
workspace=_Workspace(),
directive=DirectiveInfo(body="apply fix Y", author="can1357", thread=thread),
pr_status="PR #1080 is open",
)
assert "Directive on octo/widget#1080" in out
assert "@can1357" in out
assert "apply fix Y" in out
assert "follow up please" in out
assert "PR #1080 is open" in out
def test_kickoff_directive_prompt_embeds_thread_and_classify_instruction() -> None:
thread = (ThreadMessage(kind="issue_body", author="alice", body="failing on macos", created_at=""),)
out = persona.kickoff_directive(
repo=_Repo(),
issue=_Issue(),
workspace=_Workspace(),
directive=DirectiveInfo(body="reproduce + fix", author="can1357", thread=thread),
)
assert "Maintainer directive on octo/widget#1080" in out
assert "failing on macos" in out
assert "reproduce + fix" in out
# The kickoff variant must still tell the agent to classify first.
assert "Classify first" in out
def test_resume_triage_renders_branch_and_issue() -> None:
out = persona.resume_triage(
repo=_Repo(),
issue=_Issue(),
workspace=_Workspace(),
)
# Working branch surfaces literally so the agent sees what it's on.
assert "farm/abc/test" in out
# Issue identity surfaces with the title.
assert "octo/widget#1080" in out
assert "broken thing" in out
# The prompt instructs the agent to reconcile drift via fetch_issue_thread.
assert "fetch_issue_thread" in out