mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 06:53:14 +00:00
refactor: consolidate reviewer modules into agent/review/
Part of the domain-reorg adoption (build plan step C2): fork content,
upstream layout. Nine 1:1 module moves (reviewer_diff/eval_store/
findings/groups/publish/reconcile/trace_context + review_style_
collector/guidance) into agent/review/, with internal relative
imports re-wired to the new package depth. agent/review/__init__.py
mirrors upstream's thin re-export shim (one of the 21 verified "A"
structural adds).
Rewrote the 38 grep hits across importer files (agent/{analyzer,
ci_autofix,reviewer,webapp}.py, agent/dashboard/*, agent/middleware/
settle_review_check.py, agent/tools/*, agent/utils/github_feedback.py,
agent/webhooks/github.py, evals/reviewer/*, and the reviewer test
suite) to point at agent.review.*; 4 of the 38 hits were name
collisions (list_reviewer_findings, reviewer_outcomes,
_reviewer_thread_id, reviewer_thread_id — not the moved modules) and
were left untouched. tests/test_github_checks.py's module-alias
import (`from agent import reviewer_publish`) follows upstream's own
`from agent.review import publish as reviewer_publish` pattern so
downstream `reviewer_publish.*` call sites needed no changes.
agent/reviewer.py and agent/webapp.py stay in place per the hard
rule (fork content, import-only rewire) and are not part of this
package.
Gates: ruff check + ruff format --check, pytest --co -q (1637
collected), full unit suite (1637 passed), and the reviewer/findings
suite in isolation (pytest -k "review or finding", 421 passed).
This commit is contained in:
parent
a82da1f907
commit
62d9945df4
44 changed files with 163 additions and 152 deletions
|
|
@ -36,7 +36,7 @@ from .middleware import (
|
|||
TimeoutWrapupMiddleware,
|
||||
ToolErrorMiddleware,
|
||||
)
|
||||
from .review_style_guidance import REVIEWER_STYLE_THEMES
|
||||
from .review.style_guidance import REVIEWER_STYLE_THEMES
|
||||
from .server import (
|
||||
DEFAULT_LLM_MAX_TOKENS,
|
||||
DEFAULT_LLM_MODEL_ID,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from .dashboard.agent_overrides import load_profile, resolve_login_from_email_as
|
|||
from .dashboard.autofix_state import is_pr_autofix_disabled
|
||||
from .dashboard.enabled_repos import is_review_repo_enabled
|
||||
from .dispatch import dispatch_agent_run
|
||||
from .reviewer_findings import REVIEWER_THREAD_KIND
|
||||
from .review.findings import REVIEWER_THREAD_KIND
|
||||
from .utils.dashboard_links import dashboard_thread_url
|
||||
from .utils.github_app import get_github_app_installation_token
|
||||
from .utils.github_checks import post_autofix_status_check
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from typing import Any, Literal
|
|||
import httpx
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
from ..reviewer_findings import REVIEWER_THREAD_KIND
|
||||
from ..review.findings import REVIEWER_THREAD_KIND
|
||||
from ..utils.github_app import get_github_app_installation_token
|
||||
|
||||
USAGE_THREAD_NAMESPACE: list[str] = ["agent_usage", "threads"]
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ from typing import Any, Literal, TypedDict
|
|||
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
from agent.reviewer_eval_store import (
|
||||
from agent.review.eval_store import (
|
||||
_HEARTBEAT_STALE_SECONDS,
|
||||
DEFAULT_EVAL_PROJECT,
|
||||
EVALS_NAMESPACE,
|
||||
REVIEWER_EVAL_KEY,
|
||||
)
|
||||
from agent.reviewer_findings import REVIEW_FINDING_CAP
|
||||
from agent.review.findings import REVIEW_FINDING_CAP
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from urllib.parse import urljoin, urlparse
|
|||
import httpx
|
||||
from fastapi import HTTPException, Response
|
||||
|
||||
from ..reviewer_findings import REVIEWER_THREAD_KIND
|
||||
from ..review.findings import REVIEWER_THREAD_KIND
|
||||
from ..utils.github_app import get_github_app_installation_token
|
||||
from ..utils.github_checks import github_headers
|
||||
from ..utils.thread_ops import langgraph_client
|
||||
|
|
@ -443,7 +443,7 @@ async def create_review_comment(
|
|||
|
||||
|
||||
_HTML_COMMENT_RE = re.compile(r"<!--.*?-->", re.DOTALL)
|
||||
# Inline comments the reviewer posts carry this hidden marker (see reviewer_publish).
|
||||
# Inline comments the reviewer posts carry this hidden marker (see review.publish).
|
||||
_OPEN_SWE_COMMENT_RE = re.compile(r"<!--\s*open-swe-review-comment\b")
|
||||
_REVIEW_COMMENTS_PER_PAGE = 100
|
||||
# Bound the fetch so a pathological PR can't trigger unbounded paging (~2000 comments).
|
||||
|
|
@ -715,7 +715,7 @@ async def dry_run_trace_resolution(owner: str, repo: str, pr_number: int) -> dic
|
|||
"""Resolve a PR to its author coding-agent thread without running a review."""
|
||||
from dataclasses import asdict
|
||||
|
||||
from ..reviewer_trace_context import resolve_pr_trace
|
||||
from ..review.trace_context import resolve_pr_trace
|
||||
from ..utils.github_app import get_github_app_installation_token_with_expiry
|
||||
from ..utils.slack import GitHubPrRef
|
||||
from ..webapp import fetch_github_pr_metadata
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ from typing import Any
|
|||
import httpx
|
||||
from fastapi import HTTPException
|
||||
|
||||
from ..reviewer_diff import fetch_pr_diff
|
||||
from ..reviewer_findings import REVIEWER_THREAD_KIND
|
||||
from ..review.diff import fetch_pr_diff
|
||||
from ..review.findings import REVIEWER_THREAD_KIND
|
||||
from ..utils.github_app import get_github_app_installation_token
|
||||
from ..utils.thread_ops import langgraph_client, langgraph_url
|
||||
from .options import SUPPORTED_MODEL_IDS, model_supports_effort
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from typing import Any
|
|||
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
from ..review_style_collector import (
|
||||
from ..review.style_collector import (
|
||||
collect_review_samples,
|
||||
format_samples_for_analyzer,
|
||||
generate_review_style_thread_id,
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ from langchain.agents.middleware import AgentState, after_agent
|
|||
from langgraph.config import get_config
|
||||
from langgraph.runtime import Runtime
|
||||
|
||||
from ..reviewer_findings import get_thread_metadata
|
||||
from ..reviewer_publish import settle_review_check_run
|
||||
from ..review.findings import get_thread_metadata
|
||||
from ..review.publish import settle_review_check_run
|
||||
from ..utils.github_token import get_github_token
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
|||
11
agent/review/__init__.py
Normal file
11
agent/review/__init__.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from agent.review.findings import (
|
||||
REVIEW_FINDING_CAP,
|
||||
REVIEWER_THREAD_KIND,
|
||||
Finding,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Finding",
|
||||
"REVIEWER_THREAD_KIND",
|
||||
"REVIEW_FINDING_CAP",
|
||||
]
|
||||
|
|
@ -217,7 +217,7 @@ async def fetch_pr_diff(
|
|||
"""
|
||||
import httpx
|
||||
|
||||
from .utils.github_http import github_client, github_request
|
||||
from ..utils.github_http import github_client, github_request
|
||||
|
||||
url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
|
||||
try:
|
||||
|
|
@ -253,7 +253,7 @@ async def fetch_pr_metadata(
|
|||
"""
|
||||
import httpx
|
||||
|
||||
from .utils.github_http import github_client, github_request
|
||||
from ..utils.github_http import github_client, github_request
|
||||
|
||||
url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
|
||||
try:
|
||||
|
|
@ -22,8 +22,8 @@ from typing import TypedDict
|
|||
from langchain_core.language_models.chat_models import BaseChatModel
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .reviewer_diff import parse_unified_diff
|
||||
from .reviewer_findings import get_thread_metadata, set_reviewer_thread_metadata
|
||||
from .diff import parse_unified_diff
|
||||
from .findings import get_thread_metadata, set_reviewer_thread_metadata
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -25,22 +25,22 @@ from typing import Any, TypedDict
|
|||
|
||||
import httpx
|
||||
|
||||
from .reviewer_findings import (
|
||||
from ..utils.dashboard_links import dashboard_thread_url
|
||||
from ..utils.github_checks import CheckConclusion, complete_review_check_run
|
||||
from ..utils.github_http import (
|
||||
GITHUB_API_BASE,
|
||||
GITHUB_GRAPHQL,
|
||||
github_client,
|
||||
github_request,
|
||||
)
|
||||
from ..utils.github_token import GitHubAuthError
|
||||
from .findings import (
|
||||
DiffSide,
|
||||
Finding,
|
||||
get_thread_metadata,
|
||||
normalize_finding_title,
|
||||
set_reviewer_thread_metadata,
|
||||
)
|
||||
from .utils.dashboard_links import dashboard_thread_url
|
||||
from .utils.github_checks import CheckConclusion, complete_review_check_run
|
||||
from .utils.github_http import (
|
||||
GITHUB_API_BASE,
|
||||
GITHUB_GRAPHQL,
|
||||
github_client,
|
||||
github_request,
|
||||
)
|
||||
from .utils.github_token import GitHubAuthError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -2,14 +2,14 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any
|
||||
|
||||
from .reviewer_findings import (
|
||||
from .findings import (
|
||||
Finding,
|
||||
FindingInteraction,
|
||||
_coerce_surface,
|
||||
list_findings,
|
||||
replace_findings,
|
||||
)
|
||||
from .reviewer_publish import parse_review_comment_marker
|
||||
from .publish import parse_review_comment_marker
|
||||
|
||||
ReviewThread = dict[str, Any]
|
||||
ReviewThreadMatch = tuple[ReviewThread, int | None]
|
||||
|
|
@ -14,10 +14,10 @@ from typing import Any
|
|||
|
||||
from deepagents.backends.protocol import SandboxBackendProtocol
|
||||
|
||||
from .dashboard.team_credentials import get_langsmith_credentials
|
||||
from .dashboard.team_settings import get_team_review_tracing_project
|
||||
from .integrations.langsmith_tools import _client
|
||||
from .utils.langsmith import get_langsmith_trace_url
|
||||
from ..dashboard.team_credentials import get_langsmith_credentials
|
||||
from ..dashboard.team_settings import get_team_review_tracing_project
|
||||
from ..integrations.langsmith_tools import _client
|
||||
from ..utils.langsmith import get_langsmith_trace_url
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -55,17 +55,17 @@ from .middleware import (
|
|||
refresh_github_proxy_before_model,
|
||||
settle_review_check_on_exit,
|
||||
)
|
||||
from .reviewer_diff import compute_diff_line_set, fetch_pr_diff, fetch_pr_metadata
|
||||
from .reviewer_findings import (
|
||||
from .review.diff import compute_diff_line_set, fetch_pr_diff, fetch_pr_metadata
|
||||
from .review.findings import (
|
||||
REVIEW_FINDING_CAP,
|
||||
)
|
||||
from .reviewer_findings import (
|
||||
from .review.findings import (
|
||||
list_findings as list_findings_async,
|
||||
)
|
||||
from .reviewer_groups import maybe_generate_and_store_diff_groups
|
||||
from .reviewer_publish import fetch_pr_review_threads
|
||||
from .reviewer_reconcile import reconcile_findings_with_review_threads
|
||||
from .reviewer_trace_context import (
|
||||
from .review.groups import maybe_generate_and_store_diff_groups
|
||||
from .review.publish import fetch_pr_review_threads
|
||||
from .review.reconcile import reconcile_findings_with_review_threads
|
||||
from .review.trace_context import (
|
||||
PRTraceContext,
|
||||
format_pr_trace_context_prompt,
|
||||
prepare_pr_trace_context,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ from typing import Any
|
|||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from ..reviewer_diff import is_range_in_diff
|
||||
from ..reviewer_findings import (
|
||||
from ..review.diff import is_range_in_diff
|
||||
from ..review.findings import (
|
||||
DEFAULT_FINDING_TITLE,
|
||||
MAX_SUGGESTION_LINES,
|
||||
Confidence,
|
||||
|
|
@ -133,7 +133,7 @@ async def add_finding(
|
|||
|
||||
diff_hunk: str | None = None
|
||||
if isinstance(diff_text, str) and diff_text:
|
||||
from ..reviewer_diff import extract_diff_hunk
|
||||
from ..review.diff import extract_diff_hunk
|
||||
|
||||
diff_hunk = extract_diff_hunk(diff_text, file, start_line, end_line)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any
|
||||
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
ReviewerThreadMissingError,
|
||||
get_thread_id_from_runtime,
|
||||
thread_missing_tool_result,
|
||||
)
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
list_findings as list_findings_async,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from typing import Any
|
|||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from ..reviewer_findings import list_findings as list_findings_async
|
||||
from ..review.findings import list_findings as list_findings_async
|
||||
|
||||
_COMPACT_FIELDS = (
|
||||
"id",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ from typing import Any
|
|||
from langgraph.config import get_config
|
||||
|
||||
from ..dashboard.team_settings import get_team_review_trace_links_enabled
|
||||
from ..reviewer_diff import compute_diff_line_set, fetch_pr_diff, is_range_in_diff
|
||||
from ..reviewer_findings import (
|
||||
from ..review.diff import compute_diff_line_set, fetch_pr_diff, is_range_in_diff
|
||||
from ..review.findings import (
|
||||
REVIEW_FINDING_CAP,
|
||||
REVIEWER_EVAL_PUBLICATION_KEY,
|
||||
SEVERITY_ORDER,
|
||||
|
|
@ -26,10 +26,10 @@ from ..reviewer_findings import (
|
|||
set_reviewer_thread_metadata,
|
||||
thread_missing_tool_result,
|
||||
)
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
list_findings as list_findings_async,
|
||||
)
|
||||
from ..reviewer_publish import (
|
||||
from ..review.publish import (
|
||||
clear_review_started_comment,
|
||||
fetch_pr_review_threads,
|
||||
fetch_review_comments,
|
||||
|
|
@ -44,7 +44,7 @@ from ..reviewer_publish import (
|
|||
resolve_review_thread,
|
||||
settle_review_check_run,
|
||||
)
|
||||
from ..reviewer_reconcile import reconcile_findings_with_review_threads
|
||||
from ..review.reconcile import reconcile_findings_with_review_threads
|
||||
from ..utils.dashboard_links import dashboard_review_url
|
||||
from ..utils.github_checks import review_check_conclusion
|
||||
from ..utils.github_token import (
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Any
|
|||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
FindingInteraction,
|
||||
ReviewerThreadMissingError,
|
||||
append_finding_interaction,
|
||||
|
|
@ -13,7 +13,7 @@ from ..reviewer_findings import (
|
|||
thread_missing_tool_result,
|
||||
update_finding_fields,
|
||||
)
|
||||
from ..reviewer_publish import reply_to_review_comment
|
||||
from ..review.publish import reply_to_review_comment
|
||||
from ..utils.github_token import get_github_token
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Any
|
|||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
Finding,
|
||||
ReviewerThreadMissingError,
|
||||
get_finding,
|
||||
|
|
@ -13,14 +13,14 @@ from ..reviewer_findings import (
|
|||
update_finding_fields,
|
||||
update_finding_surface,
|
||||
)
|
||||
from ..reviewer_publish import (
|
||||
from ..review.publish import (
|
||||
fetch_pr_review_threads,
|
||||
fetch_review_thread_id_for_comment,
|
||||
render_resolution_comment,
|
||||
reply_to_review_comment,
|
||||
resolve_review_thread,
|
||||
)
|
||||
from ..reviewer_reconcile import reconcile_findings_with_review_threads
|
||||
from ..review.reconcile import reconcile_findings_with_review_threads
|
||||
from ..utils.github_token import get_github_token
|
||||
from ..utils.reviewer_outcomes import emit_finding_status_outcome
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from typing import Any
|
|||
|
||||
from langgraph.config import get_config
|
||||
|
||||
from ..reviewer_findings import (
|
||||
from ..review.findings import (
|
||||
DEFAULT_FINDING_TITLE,
|
||||
MAX_SUGGESTION_LINES,
|
||||
Finding,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from typing import Any
|
|||
from langgraph_sdk import get_client
|
||||
from langgraph_sdk.client import LangGraphClient
|
||||
|
||||
from ..reviewer_findings import list_findings
|
||||
from ..review.findings import list_findings
|
||||
from .langsmith import create_langsmith_feedback, delete_langsmith_feedback
|
||||
from .reviewer_outcomes import outcome_from_score, upsert_finding_outcome
|
||||
|
||||
|
|
|
|||
|
|
@ -49,17 +49,17 @@ from .dashboard.user_mappings import (
|
|||
)
|
||||
from .dashboard.workflow_approval import decide_workflow_push_approval
|
||||
from .dispatch import dispatch_agent_run
|
||||
from .reviewer_findings import (
|
||||
from .review.findings import (
|
||||
REVIEWER_THREAD_KIND,
|
||||
Finding,
|
||||
append_finding_interaction, # noqa: F401
|
||||
set_reviewer_thread_metadata,
|
||||
)
|
||||
from .reviewer_findings import (
|
||||
from .review.findings import (
|
||||
list_findings as list_reviewer_findings, # noqa: F401
|
||||
)
|
||||
from .reviewer_publish import fetch_pr_review_threads, post_review_started_comment # noqa: F401
|
||||
from .reviewer_reconcile import reconcile_findings_with_review_threads # noqa: F401
|
||||
from .review.publish import fetch_pr_review_threads, post_review_started_comment # noqa: F401
|
||||
from .review.reconcile import reconcile_findings_with_review_threads # noqa: F401
|
||||
from .utils.atlassian_connect import verify_connect_webhook
|
||||
from .utils.auth import (
|
||||
is_bot_token_only_mode,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from agent import webapp
|
|||
|
||||
from ..ci_autofix import handle_ci_failure, handle_review_feedback
|
||||
from ..dashboard.autofix_state import set_pr_autofix_disabled
|
||||
from ..reviewer_findings import FindingInteraction, ReviewerPRMeta, ReviewerSlackThread
|
||||
from ..review.findings import FindingInteraction, ReviewerPRMeta, ReviewerSlackThread
|
||||
from ..utils.github_ci import (
|
||||
branch_from_check_payload,
|
||||
head_sha_from_check_payload,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ from uuid import UUID
|
|||
from langchain_anthropic import ChatAnthropic
|
||||
from langsmith.schemas import Example, Run
|
||||
|
||||
from agent.reviewer_findings import REVIEW_FINDING_CAP
|
||||
from agent.review.findings import REVIEW_FINDING_CAP
|
||||
|
||||
JUDGE_MODEL = "claude-opus-4-5"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ from langgraph_sdk import get_client
|
|||
from langsmith import Client, aevaluate
|
||||
from langsmith.schemas import Example
|
||||
|
||||
from agent.reviewer_eval_store import _EXPERIMENT_URL_RE, _LOG_TAIL_CHARS
|
||||
from agent.reviewer_findings import REVIEW_FINDING_CAP
|
||||
from agent.review.eval_store import _EXPERIMENT_URL_RE, _LOG_TAIL_CHARS
|
||||
from agent.review.findings import REVIEW_FINDING_CAP
|
||||
from evals.reviewer.judge import aggregate_pr, judge_match
|
||||
from evals.reviewer.store_reporter import StoreReporter, is_enabled
|
||||
from evals.reviewer.target import (
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from typing import Any
|
|||
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
from agent.reviewer_eval_store import (
|
||||
from agent.review.eval_store import (
|
||||
_HEARTBEAT_INTERVAL_SECONDS,
|
||||
EVALS_NAMESPACE,
|
||||
REVIEWER_EVAL_KEY,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from typing import Any, Literal, cast
|
|||
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
from agent.reviewer_findings import (
|
||||
from agent.review.findings import (
|
||||
REVIEW_FINDING_CAP,
|
||||
REVIEWER_EVAL_PUBLICATION_KEY,
|
||||
Finding,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from unittest.mock import AsyncMock
|
|||
import pytest
|
||||
|
||||
from agent.dashboard import review_api, routes
|
||||
from agent.reviewer_findings import REVIEWER_THREAD_KIND
|
||||
from agent.review.findings import REVIEWER_THREAD_KIND
|
||||
|
||||
|
||||
def _thread(owner: str, name: str, number: int, author: str) -> dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from typing import Any
|
|||
import httpx
|
||||
import pytest
|
||||
|
||||
from agent import reviewer_publish
|
||||
from agent.review import publish as reviewer_publish
|
||||
from agent.utils import github_checks
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from agent.review_style_collector import (
|
||||
from agent.review.style_collector import (
|
||||
ReviewSample,
|
||||
ReviewStyleSamples,
|
||||
format_samples_for_analyzer,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_diff import (
|
||||
from agent.review.diff import (
|
||||
compute_diff_line_set,
|
||||
extract_diff_hunk,
|
||||
is_range_in_diff,
|
||||
|
|
@ -103,7 +103,7 @@ async def test_compute_diff_in_sandbox_uses_three_dot_for_merge_base() -> None:
|
|||
"""First-review path passes merge_base=True so we use base...head, not base..head."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from agent.reviewer_diff import compute_diff_in_sandbox
|
||||
from agent.review.diff import compute_diff_in_sandbox
|
||||
|
||||
backend = MagicMock()
|
||||
backend.execute = MagicMock(return_value="")
|
||||
|
|
@ -122,7 +122,7 @@ async def test_compute_diff_in_sandbox_uses_two_dot_by_default() -> None:
|
|||
"""Re-review delta path passes merge_base=False so we use base..head."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from agent.reviewer_diff import compute_diff_in_sandbox
|
||||
from agent.review.diff import compute_diff_in_sandbox
|
||||
|
||||
backend = MagicMock()
|
||||
backend.execute = MagicMock(return_value="")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Any
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_findings import new_finding
|
||||
from agent.review.findings import new_finding
|
||||
from evals.reviewer import target
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_findings import (
|
||||
from agent.review.findings import (
|
||||
SEVERITY_ORDER,
|
||||
DiffSide,
|
||||
Finding,
|
||||
|
|
@ -120,7 +120,7 @@ def test_filter_findings_for_publish_caps_results() -> None:
|
|||
async def test_list_findings_returns_empty_on_missing_metadata() -> None:
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {}}
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
findings = await list_findings("tid")
|
||||
assert findings == []
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ async def test_list_findings_coerces_bad_entries() -> None:
|
|||
]
|
||||
}
|
||||
}
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
findings = await list_findings("tid")
|
||||
assert [f["id"] for f in findings] == ["f_ok"]
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ async def test_list_findings_coerces_bad_entries() -> None:
|
|||
async def test_replace_findings_calls_threads_update() -> None:
|
||||
fake_client = AsyncMock()
|
||||
findings = [_f(id="f_x")]
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
await replace_findings("tid", findings)
|
||||
fake_client.threads.update.assert_awaited_once_with(
|
||||
thread_id="tid", metadata={"findings": findings}
|
||||
|
|
@ -161,7 +161,7 @@ async def test_append_finding_appends_to_existing_list() -> None:
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {"findings": [existing]}}
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
result = await append_finding("tid", new)
|
||||
|
||||
assert result["finding"]["id"] == "f_b"
|
||||
|
|
@ -193,7 +193,7 @@ async def test_concurrent_append_finding_preserves_distinct_findings() -> None:
|
|||
class Client:
|
||||
threads = Threads()
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=Client()):
|
||||
with patch("agent.review.findings.get_client", return_value=Client()):
|
||||
first, second = await asyncio.gather(
|
||||
append_finding("tid", _f(id="f_a", description="first")),
|
||||
append_finding("tid", _f(id="f_b", description="second")),
|
||||
|
|
@ -224,7 +224,7 @@ async def test_concurrent_identical_findings_are_idempotent() -> None:
|
|||
class Client:
|
||||
threads = Threads()
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=Client()):
|
||||
with patch("agent.review.findings.get_client", return_value=Client()):
|
||||
first, second = await asyncio.gather(
|
||||
append_finding("tid", _f(id="f_a")),
|
||||
append_finding("tid", _f(id="f_b")),
|
||||
|
|
@ -250,7 +250,7 @@ async def test_mutate_findings_reads_latest_before_mutating() -> None:
|
|||
findings[0]["status"] = "resolved"
|
||||
return True
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
result = await mutate_findings("tid", _mutator)
|
||||
|
||||
assert seen == ["f_fresh"]
|
||||
|
|
@ -265,7 +265,7 @@ async def test_mutate_findings_skips_write_when_unchanged() -> None:
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {"findings": [_f(id="f_a")]}}
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
await mutate_findings("tid", lambda _findings: False)
|
||||
|
||||
fake_client.threads.update.assert_not_called()
|
||||
|
|
@ -276,7 +276,7 @@ async def test_mutate_findings_does_not_write_after_transient_read_failure() ->
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.side_effect = RuntimeError("transient")
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
with pytest.raises(RuntimeError, match="transient"):
|
||||
await mutate_findings("tid", lambda findings: bool(findings.append(_f(id="f_new"))))
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ async def test_update_finding_fields_mutates_only_target() -> None:
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {"findings": [a, b]}}
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
updated = await update_finding_fields("tid", "f_b", {"status": "resolved"})
|
||||
|
||||
assert updated is not None
|
||||
|
|
@ -306,7 +306,7 @@ async def test_update_finding_fields_mutates_only_target() -> None:
|
|||
async def test_update_finding_fields_returns_none_for_unknown_id() -> None:
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {"findings": [_f(id="f_a")]}}
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
result = await update_finding_fields("tid", "f_missing", {"status": "resolved"})
|
||||
assert result is None
|
||||
fake_client.threads.update.assert_not_called()
|
||||
|
|
@ -315,7 +315,7 @@ async def test_update_finding_fields_returns_none_for_unknown_id() -> None:
|
|||
@pytest.mark.asyncio
|
||||
async def test_set_reviewer_thread_metadata_includes_kind() -> None:
|
||||
fake_client = AsyncMock()
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
await set_reviewer_thread_metadata("tid", watch=True, last_reviewed_sha="sha")
|
||||
metadata = fake_client.threads.update.await_args.kwargs["metadata"]
|
||||
assert metadata["kind"] == "reviewer"
|
||||
|
|
@ -328,7 +328,7 @@ async def test_set_reviewer_thread_metadata_includes_kind() -> None:
|
|||
@pytest.mark.asyncio
|
||||
async def test_set_reviewer_thread_metadata_persists_head_sha() -> None:
|
||||
fake_client = AsyncMock()
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
await set_reviewer_thread_metadata("tid", head_sha="newhead")
|
||||
metadata = fake_client.threads.update.await_args.kwargs["metadata"]
|
||||
assert metadata["head_sha"] == "newhead"
|
||||
|
|
@ -340,7 +340,7 @@ async def test_resolve_review_head_sha_prefers_metadata_over_config() -> None:
|
|||
the stale head frozen in the run's config."""
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {"head_sha": "metahead"}}
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
head = await resolve_review_head_sha("tid", {"head_sha": "confighead"})
|
||||
assert head == "metahead"
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ async def test_resolve_review_head_sha_prefers_metadata_over_config() -> None:
|
|||
async def test_resolve_review_head_sha_falls_back_to_config_when_metadata_empty() -> None:
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.return_value = {"metadata": {}}
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
head = await resolve_review_head_sha("tid", {"head_sha": "confighead"})
|
||||
assert head == "confighead"
|
||||
|
||||
|
|
@ -357,7 +357,7 @@ async def test_resolve_review_head_sha_falls_back_to_config_when_metadata_empty(
|
|||
@pytest.mark.asyncio
|
||||
async def test_resolve_review_head_sha_falls_back_without_thread_id() -> None:
|
||||
fake_client = AsyncMock()
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
head = await resolve_review_head_sha("", {"head_sha": "confighead"})
|
||||
assert head == "confighead"
|
||||
fake_client.threads.get.assert_not_called()
|
||||
|
|
@ -368,7 +368,7 @@ async def test_replace_findings_raises_domain_error_when_thread_missing() -> Non
|
|||
import httpx
|
||||
from langgraph_sdk.errors import NotFoundError
|
||||
|
||||
from agent.reviewer_findings import ReviewerThreadMissingError
|
||||
from agent.review.findings import ReviewerThreadMissingError
|
||||
|
||||
not_found = NotFoundError(
|
||||
"thread tid not found",
|
||||
|
|
@ -378,7 +378,7 @@ async def test_replace_findings_raises_domain_error_when_thread_missing() -> Non
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.update.side_effect = not_found
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
with pytest.raises(ReviewerThreadMissingError) as excinfo:
|
||||
await replace_findings("tid", [_f(id="f_a")])
|
||||
|
||||
|
|
@ -402,30 +402,30 @@ async def test_get_thread_metadata_raises_domain_error_when_thread_missing() ->
|
|||
"""A missing thread must surface as ReviewerThreadMissingError, not be
|
||||
swallowed into ``{}`` — that produced misleading tool results like
|
||||
"No finding found" instead of the do-not-retry contract."""
|
||||
from agent.reviewer_findings import ReviewerThreadMissingError, get_thread_metadata
|
||||
from agent.review.findings import ReviewerThreadMissingError, get_thread_metadata
|
||||
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.side_effect = _not_found()
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
with pytest.raises(ReviewerThreadMissingError):
|
||||
await get_thread_metadata("tid")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_thread_metadata_still_degrades_on_other_failures() -> None:
|
||||
from agent.reviewer_findings import get_thread_metadata
|
||||
from agent.review.findings import get_thread_metadata
|
||||
|
||||
fake_client = AsyncMock()
|
||||
fake_client.threads.get.side_effect = RuntimeError("transient")
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
assert await get_thread_metadata("tid") == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_set_reviewer_thread_metadata_raises_domain_error_when_thread_missing() -> None:
|
||||
from agent.reviewer_findings import (
|
||||
from agent.review.findings import (
|
||||
ReviewerThreadMissingError,
|
||||
set_reviewer_thread_metadata,
|
||||
)
|
||||
|
|
@ -433,6 +433,6 @@ async def test_set_reviewer_thread_metadata_raises_domain_error_when_thread_miss
|
|||
fake_client = AsyncMock()
|
||||
fake_client.threads.update.side_effect = _not_found("PATCH")
|
||||
|
||||
with patch("agent.reviewer_findings.get_client", return_value=fake_client):
|
||||
with patch("agent.review.findings.get_client", return_value=fake_client):
|
||||
with pytest.raises(ReviewerThreadMissingError):
|
||||
await set_reviewer_thread_metadata("tid", last_reviewed_sha="sha")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_groups import (
|
||||
from agent.review.groups import (
|
||||
_build_prompt,
|
||||
_DiffGroupingResult,
|
||||
_DiffGroupModel,
|
||||
|
|
@ -124,13 +124,13 @@ async def test_maybe_generate_skips_when_signature_unchanged() -> None:
|
|||
}
|
||||
with (
|
||||
patch(
|
||||
"agent.reviewer_groups.get_thread_metadata",
|
||||
"agent.review.groups.get_thread_metadata",
|
||||
new_callable=AsyncMock,
|
||||
return_value=existing,
|
||||
),
|
||||
patch("agent.reviewer_groups.generate_diff_groups", new_callable=AsyncMock) as gen,
|
||||
patch("agent.review.groups.generate_diff_groups", new_callable=AsyncMock) as gen,
|
||||
patch(
|
||||
"agent.reviewer_groups.set_reviewer_thread_metadata",
|
||||
"agent.review.groups.set_reviewer_thread_metadata",
|
||||
new_callable=AsyncMock,
|
||||
) as set_meta,
|
||||
):
|
||||
|
|
@ -146,17 +146,17 @@ async def test_maybe_generate_stores_when_changed() -> None:
|
|||
groups = [{"title": "t", "summary": "s", "files": ["foo.py"]}]
|
||||
with (
|
||||
patch(
|
||||
"agent.reviewer_groups.get_thread_metadata",
|
||||
"agent.review.groups.get_thread_metadata",
|
||||
new_callable=AsyncMock,
|
||||
return_value={},
|
||||
),
|
||||
patch(
|
||||
"agent.reviewer_groups.generate_diff_groups",
|
||||
"agent.review.groups.generate_diff_groups",
|
||||
new_callable=AsyncMock,
|
||||
return_value=groups,
|
||||
) as gen,
|
||||
patch(
|
||||
"agent.reviewer_groups.set_reviewer_thread_metadata",
|
||||
"agent.review.groups.set_reviewer_thread_metadata",
|
||||
new_callable=AsyncMock,
|
||||
) as set_meta,
|
||||
):
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_findings import Finding, new_finding
|
||||
from agent.reviewer_publish import (
|
||||
from agent.review.findings import Finding, new_finding
|
||||
from agent.review.publish import (
|
||||
clear_review_started_comment,
|
||||
fetch_pr_review_threads,
|
||||
open_swe_review_exists,
|
||||
|
|
@ -278,10 +278,10 @@ async def test_post_review_started_comment_posts_and_persists_id() -> None:
|
|||
post = AsyncMock(return_value=4242)
|
||||
set_meta = AsyncMock()
|
||||
with (
|
||||
patch("agent.reviewer_publish.get_thread_metadata", AsyncMock(return_value={})),
|
||||
patch("agent.reviewer_publish.post_status_comment", post),
|
||||
patch("agent.reviewer_publish.delete_status_comment", AsyncMock()) as delete,
|
||||
patch("agent.reviewer_publish.set_reviewer_thread_metadata", set_meta),
|
||||
patch("agent.review.publish.get_thread_metadata", AsyncMock(return_value={})),
|
||||
patch("agent.review.publish.post_status_comment", post),
|
||||
patch("agent.review.publish.delete_status_comment", AsyncMock()) as delete,
|
||||
patch("agent.review.publish.set_reviewer_thread_metadata", set_meta),
|
||||
):
|
||||
cid = await post_review_started_comment(
|
||||
thread_id="tid", owner="o", repo="r", pr_number=7, token="t"
|
||||
|
|
@ -298,12 +298,12 @@ async def test_post_review_started_comment_deletes_lingering_before_reposting()
|
|||
delete = AsyncMock(return_value=True)
|
||||
with (
|
||||
patch(
|
||||
"agent.reviewer_publish.get_thread_metadata",
|
||||
"agent.review.publish.get_thread_metadata",
|
||||
AsyncMock(return_value={"status_comment_id": 99}),
|
||||
),
|
||||
patch("agent.reviewer_publish.post_status_comment", post),
|
||||
patch("agent.reviewer_publish.delete_status_comment", delete),
|
||||
patch("agent.reviewer_publish.set_reviewer_thread_metadata", AsyncMock()),
|
||||
patch("agent.review.publish.post_status_comment", post),
|
||||
patch("agent.review.publish.delete_status_comment", delete),
|
||||
patch("agent.review.publish.set_reviewer_thread_metadata", AsyncMock()),
|
||||
):
|
||||
cid = await post_review_started_comment(
|
||||
thread_id="tid", owner="o", repo="r", pr_number=7, token="t"
|
||||
|
|
@ -319,11 +319,11 @@ async def test_clear_review_started_comment_deletes_and_clears_metadata() -> Non
|
|||
set_meta = AsyncMock()
|
||||
with (
|
||||
patch(
|
||||
"agent.reviewer_publish.get_thread_metadata",
|
||||
"agent.review.publish.get_thread_metadata",
|
||||
AsyncMock(return_value={"status_comment_id": 99}),
|
||||
),
|
||||
patch("agent.reviewer_publish.delete_status_comment", delete),
|
||||
patch("agent.reviewer_publish.set_reviewer_thread_metadata", set_meta),
|
||||
patch("agent.review.publish.delete_status_comment", delete),
|
||||
patch("agent.review.publish.set_reviewer_thread_metadata", set_meta),
|
||||
):
|
||||
await clear_review_started_comment(thread_id="tid", owner="o", repo="r", token="t")
|
||||
delete.assert_awaited_once()
|
||||
|
|
@ -336,9 +336,9 @@ async def test_clear_review_started_comment_noop_without_tracked_id() -> None:
|
|||
delete = AsyncMock()
|
||||
set_meta = AsyncMock()
|
||||
with (
|
||||
patch("agent.reviewer_publish.get_thread_metadata", AsyncMock(return_value={})),
|
||||
patch("agent.reviewer_publish.delete_status_comment", delete),
|
||||
patch("agent.reviewer_publish.set_reviewer_thread_metadata", set_meta),
|
||||
patch("agent.review.publish.get_thread_metadata", AsyncMock(return_value={})),
|
||||
patch("agent.review.publish.delete_status_comment", delete),
|
||||
patch("agent.review.publish.set_reviewer_thread_metadata", set_meta),
|
||||
):
|
||||
await clear_review_started_comment(thread_id="tid", owner="o", repo="r", token="t")
|
||||
delete.assert_not_called()
|
||||
|
|
@ -1145,8 +1145,8 @@ async def test_re_review_backfills_existing_marker_and_skips_duplicate_post() ->
|
|||
"agent.tools.publish_review.fetch_pr_review_threads", AsyncMock(return_value=[thread])
|
||||
),
|
||||
patch("agent.tools.publish_review.list_findings_async", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", AsyncMock()),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", AsyncMock()),
|
||||
patch("agent.tools.publish_review.post_pull_request_review", post_review),
|
||||
patch(
|
||||
"agent.tools.publish_review._resolve_threads_for_resolved_findings",
|
||||
|
|
@ -1221,8 +1221,8 @@ async def test_re_review_backfills_and_resolves_duplicate_existing_threads() ->
|
|||
"agent.tools.publish_review.fetch_pr_review_threads", AsyncMock(return_value=threads)
|
||||
),
|
||||
patch("agent.tools.publish_review.list_findings_async", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", AsyncMock()),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", AsyncMock()),
|
||||
patch("agent.tools.publish_review.post_pull_request_review", AsyncMock()),
|
||||
patch("agent.tools.publish_review.resolve_review_thread", resolve_thread),
|
||||
patch(
|
||||
|
|
@ -1284,8 +1284,8 @@ async def test_publish_review_backfills_from_threads_when_review_comments_are_em
|
|||
patch("agent.tools.publish_review.get_thread_id_from_runtime", return_value="tid"),
|
||||
patch("agent.tools.publish_review.fetch_pr_review_threads", fetch_threads),
|
||||
patch("agent.tools.publish_review.list_findings_async", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", AsyncMock()),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", AsyncMock()),
|
||||
patch(
|
||||
"agent.tools.publish_review.post_pull_request_review",
|
||||
AsyncMock(return_value={"id": 999}),
|
||||
|
|
@ -2242,7 +2242,7 @@ async def test_publish_review_fetches_pr_diff_when_diff_line_set_missing() -> No
|
|||
async def test_publish_review_tool_returns_structured_error_when_thread_missing() -> None:
|
||||
"""A missing reviewer thread surfaces as a do-not-retry tool result instead
|
||||
of an exception the middleware swallows into an empty tool message."""
|
||||
from agent.reviewer_findings import ReviewerThreadMissingError
|
||||
from agent.review.findings import ReviewerThreadMissingError
|
||||
from agent.tools.publish_review import publish_review
|
||||
|
||||
publish_async = AsyncMock(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from agent.reviewer_reconcile import reconcile_findings_with_review_threads
|
||||
from agent.review.reconcile import reconcile_findings_with_review_threads
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -20,8 +20,8 @@ async def test_reconcile_marks_resolved_github_thread_resolved() -> None:
|
|||
replace = AsyncMock()
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -53,8 +53,8 @@ async def test_reconcile_backfills_comment_and_thread_ids_from_bot_marker() -> N
|
|||
replace = AsyncMock()
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -98,8 +98,8 @@ async def test_reconcile_backfills_marker_from_graphql_app_login() -> None:
|
|||
replace = AsyncMock()
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -146,8 +146,8 @@ async def test_reconcile_duplicate_markers_require_all_threads_terminal() -> Non
|
|||
)
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -191,8 +191,8 @@ async def test_reconcile_duplicate_markers_stay_open_when_some_threads_only_outd
|
|||
)
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -232,8 +232,8 @@ async def test_reconcile_ignores_spoofed_non_bot_marker() -> None:
|
|||
replace = AsyncMock()
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
@ -268,8 +268,8 @@ async def test_reconcile_records_latest_human_reply_after_bot_comment() -> None:
|
|||
replace = AsyncMock()
|
||||
|
||||
with (
|
||||
patch("agent.reviewer_reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.reviewer_reconcile.replace_findings", replace),
|
||||
patch("agent.review.reconcile.list_findings", AsyncMock(return_value=findings)),
|
||||
patch("agent.review.reconcile.replace_findings", replace),
|
||||
):
|
||||
result = await reconcile_findings_with_review_threads(
|
||||
"tid",
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ async def test_list_findings_returns_all_when_filter_omitted() -> None:
|
|||
async def test_add_finding_returns_structured_error_when_thread_missing() -> None:
|
||||
"""A missing reviewer thread must come back as a do-not-retry tool result,
|
||||
not a raised exception the agent retries against 10-30 times."""
|
||||
from agent.reviewer_findings import ReviewerThreadMissingError
|
||||
from agent.review.findings import ReviewerThreadMissingError
|
||||
|
||||
async def fake_append(thread_id: str, finding: Any) -> Any:
|
||||
raise ReviewerThreadMissingError(thread_id, RuntimeError("thread X not found"))
|
||||
|
|
@ -746,7 +746,7 @@ async def test_add_finding_returns_structured_error_when_thread_missing() -> Non
|
|||
|
||||
|
||||
async def test_update_finding_returns_structured_error_when_thread_missing() -> None:
|
||||
from agent.reviewer_findings import ReviewerThreadMissingError
|
||||
from agent.review.findings import ReviewerThreadMissingError
|
||||
|
||||
async def fake_update(thread_id: str, finding_id: str, updates: Any) -> Any:
|
||||
raise ReviewerThreadMissingError(thread_id, RuntimeError("thread X not found"))
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, patch
|
|||
import pytest
|
||||
|
||||
from agent.dashboard.team_credentials import LangSmithCredentials
|
||||
from agent.reviewer_trace_context import (
|
||||
from agent.review.trace_context import (
|
||||
PRTraceContext,
|
||||
format_pr_trace_context_prompt,
|
||||
prepare_pr_trace_context,
|
||||
|
|
@ -108,15 +108,15 @@ def _patches(client: _FakeLangSmithClient) -> Any:
|
|||
creds = LangSmithCredentials(api_key="k", endpoint="https://api.smith.langchain.com")
|
||||
return (
|
||||
patch(
|
||||
"agent.reviewer_trace_context.get_team_review_tracing_project",
|
||||
"agent.review.trace_context.get_team_review_tracing_project",
|
||||
AsyncMock(return_value="pajuha"),
|
||||
),
|
||||
patch(
|
||||
"agent.reviewer_trace_context.get_langsmith_credentials", AsyncMock(return_value=creds)
|
||||
"agent.review.trace_context.get_langsmith_credentials", AsyncMock(return_value=creds)
|
||||
),
|
||||
patch("agent.reviewer_trace_context._client", return_value=client),
|
||||
patch("agent.review.trace_context._client", return_value=client),
|
||||
patch(
|
||||
"agent.reviewer_trace_context.get_langsmith_trace_url",
|
||||
"agent.review.trace_context.get_langsmith_trace_url",
|
||||
return_value="https://smith/t/thread-1",
|
||||
),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue