chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
"""Tests for meta-codereview-current-diff (Round-2 combinator).
|
||||
|
||||
Three independent reviewers (safety + tests + style) run in parallel
|
||||
over the diff; arbitrate applies strict priority CRITICAL > WARNING/
|
||||
MISSING > clean.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncIterator
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from opensquilla.engine.types import AgentEvent, DoneEvent, TextDeltaEvent
|
||||
from opensquilla.skills.loader import SkillLoader
|
||||
from opensquilla.skills.meta.orchestrator import MetaOrchestrator
|
||||
from opensquilla.skills.meta.parser import parse_meta_plan
|
||||
from opensquilla.skills.meta.types import MetaMatch
|
||||
|
||||
_BUNDLED = (
|
||||
Path(__file__).resolve().parents[2] / "src" / "opensquilla" / "skills" / "bundled"
|
||||
)
|
||||
_EXP = Path(__file__).resolve().parents[2] / "src" / "opensquilla" / "skills" / "exp"
|
||||
|
||||
|
||||
def _bundle_loader(tmp_path: Path) -> SkillLoader:
|
||||
loader = SkillLoader(
|
||||
bundled_dir=_BUNDLED,
|
||||
extra_dirs=[_EXP],
|
||||
snapshot_path=tmp_path / "snap.json",
|
||||
)
|
||||
loader.invalidate_cache()
|
||||
loader.load_all()
|
||||
return loader
|
||||
|
||||
|
||||
def test_parses_with_expected_topology(tmp_path: Path) -> None:
|
||||
loader = _bundle_loader(tmp_path)
|
||||
spec = loader.get_by_name("meta-codereview-current-diff")
|
||||
assert spec is not None
|
||||
plan = parse_meta_plan(spec)
|
||||
assert plan is not None
|
||||
|
||||
step_ids = [s.id for s in plan.steps]
|
||||
assert step_ids == [
|
||||
"read_diff",
|
||||
"review_safety",
|
||||
"review_tests",
|
||||
"review_style",
|
||||
"arbitrate",
|
||||
]
|
||||
by_id = {s.id: s for s in plan.steps}
|
||||
for r in ("review_safety", "review_tests", "review_style"):
|
||||
assert by_id[r].kind == "llm_chat"
|
||||
assert by_id[r].depends_on == ("read_diff",)
|
||||
assert by_id["arbitrate"].kind == "llm_chat"
|
||||
assert set(by_id["arbitrate"].depends_on) == {
|
||||
"review_safety",
|
||||
"review_tests",
|
||||
"review_style",
|
||||
}
|
||||
|
||||
|
||||
def _classify(user_message: str) -> str:
|
||||
# Arbitrate first (embeds the per-reviewer step ids).
|
||||
if "Three reviewers ran on the diff" in user_message:
|
||||
return "arbitrate"
|
||||
if "git diff --cached HEAD" in user_message:
|
||||
return "read_diff"
|
||||
if "safety reviewer" in user_message:
|
||||
return "review_safety"
|
||||
if "test-coverage reviewer" in user_message:
|
||||
return "review_tests"
|
||||
if "style / idiom reviewer" in user_message:
|
||||
return "review_style"
|
||||
return "other"
|
||||
|
||||
|
||||
def _arbitrate(safety: str, tests: str, style: str) -> str:
|
||||
if safety.startswith("CRITICAL"):
|
||||
return f"BLOCK: {safety}"
|
||||
if safety.startswith("WARNING") or tests.startswith("MISSING_TESTS"):
|
||||
bits = []
|
||||
if safety.startswith("WARNING"):
|
||||
bits.append(safety)
|
||||
if tests.startswith("MISSING_TESTS"):
|
||||
bits.append(tests)
|
||||
return f"BLOCK_WITH_OVERRIDE: {'; '.join(bits)}"
|
||||
note = style if style.startswith("ANTIPATTERNS") else "clean"
|
||||
return f"PASS_WITH_NOTES: {note}"
|
||||
|
||||
|
||||
async def _run(
|
||||
tmp_path: Path,
|
||||
*,
|
||||
safety_verdict: str,
|
||||
tests_verdict: str,
|
||||
style_verdict: str,
|
||||
user_message: str = "multi-reviewer diff",
|
||||
) -> dict[str, str]:
|
||||
loader = _bundle_loader(tmp_path)
|
||||
spec = loader.get_by_name("meta-codereview-current-diff")
|
||||
plan = parse_meta_plan(spec)
|
||||
assert plan is not None
|
||||
|
||||
async def runner(_system: str, user_msg: str) -> AsyncIterator[AgentEvent]:
|
||||
which = _classify(user_msg)
|
||||
if which == "read_diff":
|
||||
yield TextDeltaEvent(
|
||||
text="diff --git a/foo.py b/foo.py\n+def new_public():\n+ pass\n",
|
||||
)
|
||||
elif which == "review_safety":
|
||||
yield TextDeltaEvent(text=safety_verdict)
|
||||
elif which == "review_tests":
|
||||
yield TextDeltaEvent(text=tests_verdict)
|
||||
elif which == "review_style":
|
||||
yield TextDeltaEvent(text=style_verdict)
|
||||
elif which == "arbitrate":
|
||||
yield TextDeltaEvent(
|
||||
text=_arbitrate(safety_verdict, tests_verdict, style_verdict),
|
||||
)
|
||||
else:
|
||||
yield TextDeltaEvent(text="memory record saved")
|
||||
yield DoneEvent(text="")
|
||||
|
||||
orch = MetaOrchestrator(agent_runner=runner, skill_loader=loader)
|
||||
result = await orch.run(
|
||||
MetaMatch(plan=plan, inputs={"user_message": user_message}),
|
||||
)
|
||||
assert result.ok, f"plan failed: {result.error}"
|
||||
return result.step_outputs
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_safety_critical_blocks(tmp_path: Path) -> None:
|
||||
outputs = await _run(
|
||||
tmp_path,
|
||||
safety_verdict="CRITICAL: SQL injection via f-string in user_query",
|
||||
tests_verdict="PASS: tests adequate",
|
||||
style_verdict="CLEAN: no style issues found",
|
||||
)
|
||||
verdict = outputs["arbitrate"]
|
||||
assert verdict.startswith("BLOCK:"), f"got {verdict!r}"
|
||||
assert "SQL injection" in verdict
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_missing_tests_block_with_override(tmp_path: Path) -> None:
|
||||
outputs = await _run(
|
||||
tmp_path,
|
||||
safety_verdict="CLEAR: no safety concerns found",
|
||||
tests_verdict="MISSING_TESTS: new_public lacks tests",
|
||||
style_verdict="CLEAN: no style issues found",
|
||||
)
|
||||
verdict = outputs["arbitrate"]
|
||||
assert verdict.startswith("BLOCK_WITH_OVERRIDE"), f"got {verdict!r}"
|
||||
assert "new_public" in verdict
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_all_clean_pass_with_notes(tmp_path: Path) -> None:
|
||||
outputs = await _run(
|
||||
tmp_path,
|
||||
safety_verdict="CLEAR: no safety concerns found",
|
||||
tests_verdict="PASS: tests adequate",
|
||||
style_verdict="CLEAN: no style issues found",
|
||||
)
|
||||
verdict = outputs["arbitrate"]
|
||||
assert verdict.startswith("PASS_WITH_NOTES"), f"got {verdict!r}"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_safety_critical_overrides_missing_tests(tmp_path: Path) -> None:
|
||||
"""Strict priority: safety CRITICAL wins over tests MISSING_TESTS."""
|
||||
outputs = await _run(
|
||||
tmp_path,
|
||||
safety_verdict="CRITICAL: hardcoded credential sk-xxxx",
|
||||
tests_verdict="MISSING_TESTS: tests not added",
|
||||
style_verdict="ANTIPATTERNS: bare except at foo.py:12",
|
||||
)
|
||||
verdict = outputs["arbitrate"]
|
||||
assert verdict.startswith("BLOCK:"), f"got {verdict!r}"
|
||||
assert "sk-xxxx" in verdict
|
||||
Reference in New Issue
Block a user