chore: mark TASK-006 complete
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from rdb_discovery.guardrails import (
|
||||
check_repeated_reads,
|
||||
check_repeated_commands,
|
||||
check_no_recent_file_changes,
|
||||
check_no_test_run_recorded,
|
||||
check_run_log_updated,
|
||||
run_all_guardrails,
|
||||
format_report,
|
||||
)
|
||||
|
||||
|
||||
# -- check_repeated_reads --
|
||||
|
||||
def test_check_repeated_reads_ok(tmp_path: Path) -> None:
|
||||
"""No agent history files → status ok."""
|
||||
result = check_repeated_reads(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
def test_check_repeated_reads_warning(tmp_path: Path) -> None:
|
||||
"""AGENT_HANDOFF.md mentions the same file >2 times."""
|
||||
ah = tmp_path / "AGENT_HANDOFF.md"
|
||||
ah.write_text(
|
||||
"# Agent Handoff\n\n"
|
||||
"- README.md\n- README.md\n- README.md\n"
|
||||
"- TASKS.md\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_repeated_reads(tmp_path)
|
||||
assert result["status"] == "warning"
|
||||
assert "README.md (3x)" in result["details"]
|
||||
|
||||
|
||||
def test_check_repeated_reads_no_over_threshold(tmp_path: Path) -> None:
|
||||
"""Files mentioned <=2 times should not trigger warning."""
|
||||
ah = tmp_path / "AGENT_HANDOFF.md"
|
||||
ah.write_text(
|
||||
"# Agent Handoff\n\n"
|
||||
"- README.md\n- README.md\n"
|
||||
"- TASKS.md\n- TASKS.md\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_repeated_reads(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
# -- check_repeated_commands --
|
||||
|
||||
def test_check_repeated_commands_ok_no_log(tmp_path: Path) -> None:
|
||||
result = check_repeated_commands(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
def test_check_repeated_commands_ok(tmp_path: Path) -> None:
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
rl.write_text(
|
||||
"| date | event1 |\n"
|
||||
"| date | event2 |\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_repeated_commands(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
def test_check_repeated_commands_warning(tmp_path: Path) -> None:
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
line = "| date | Task completed |\n"
|
||||
rl.write_text(
|
||||
"# RUN_LOG\n\n| Date | Event | Task | Notes |\n" + line * 5,
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_repeated_commands(tmp_path)
|
||||
assert result["status"] == "warning"
|
||||
|
||||
|
||||
# -- check_no_recent_file_changes --
|
||||
|
||||
def test_check_no_recent_file_changes_ok(tmp_path: Path) -> None:
|
||||
"""Files modified recently → ok."""
|
||||
for rel in ["TASKS.md", "PROJECT_STATE.md"]:
|
||||
(tmp_path / rel).write_text("x", encoding="utf-8")
|
||||
|
||||
# Patch _last_modified to return a recent time
|
||||
import rdb_discovery.guardrails as mod
|
||||
original_now = mod._now
|
||||
|
||||
def fake_now() -> datetime:
|
||||
return datetime.now()
|
||||
|
||||
mod._now = fake_now
|
||||
try:
|
||||
result = check_no_recent_file_changes(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
finally:
|
||||
mod._now = original_now
|
||||
|
||||
|
||||
def test_check_no_recent_file_changes_warning(tmp_path: Path) -> None:
|
||||
"""Files modified >48h ago → warning."""
|
||||
(tmp_path / "TASKS.md").write_text("x", encoding="utf-8")
|
||||
|
||||
import rdb_discovery.guardrails as mod
|
||||
|
||||
old_ts = datetime.now() - timedelta(hours=72)
|
||||
# Set a fake mtime via os.utime (avoids pathlib.touch times= on macOS)
|
||||
ts = old_ts.timestamp()
|
||||
(tmp_path / "TASKS.md").touch()
|
||||
os.utime(str(tmp_path / "TASKS.md"), (ts, ts))
|
||||
|
||||
result = check_no_recent_file_changes(tmp_path)
|
||||
assert result["status"] == "warning"
|
||||
|
||||
|
||||
# -- check_no_test_run_recorded --
|
||||
|
||||
def test_check_no_test_run_recorded_ok(tmp_path: Path) -> None:
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
rl.write_text("# RUN\n\n| date | pytest passed |\n", encoding="utf-8")
|
||||
result = check_no_test_run_recorded(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
def test_check_no_test_run_recorded_warning(tmp_path: Path) -> None:
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
rl.write_text("# RUN\n\n| date | task done |\n", encoding="utf-8")
|
||||
result = check_no_test_run_recorded(tmp_path)
|
||||
assert result["status"] == "warning"
|
||||
|
||||
|
||||
def test_check_no_test_run_recorded_no_log(tmp_path: Path) -> None:
|
||||
result = check_no_test_run_recorded(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
# -- check_run_log_updated --
|
||||
|
||||
def test_check_run_log_updated_ok(tmp_path: Path) -> None:
|
||||
tasks = tmp_path / "TASKS.md"
|
||||
tasks.write_text(
|
||||
"## TASK-001 - First\nStatus: Done\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
rl.write_text(
|
||||
"# RUN\n\n| date | Task completed | TASK-001 |\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_run_log_updated(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
def test_check_run_log_updated_warning(tmp_path: Path) -> None:
|
||||
tasks = tmp_path / "TASKS.md"
|
||||
tasks.write_text(
|
||||
"## TASK-001 - First\nStatus: Done\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
rl = tmp_path / "RUN_LOG.md"
|
||||
rl.write_text("# RUN\n\n| date | something else |\n", encoding="utf-8")
|
||||
result = check_run_log_updated(tmp_path)
|
||||
assert result["status"] == "warning"
|
||||
|
||||
|
||||
def test_check_run_log_updated_no_files(tmp_path: Path) -> None:
|
||||
result = check_run_log_updated(tmp_path)
|
||||
assert result["status"] == "ok"
|
||||
|
||||
|
||||
# -- run_all_guardrails --
|
||||
|
||||
def test_run_all_guardrails_returns_keys() -> None:
|
||||
import tempfile
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
root = Path(td)
|
||||
# Create minimal files so checks don't return 'ok' for missing file
|
||||
(root / "RUN_LOG.md").write_text("# RUN\n", encoding="utf-8")
|
||||
result = run_all_guardrails(root)
|
||||
assert "checks" in result
|
||||
assert "overall_status" in result
|
||||
|
||||
|
||||
def test_run_all_guardrails_overall_all_clear(tmp_path: Path) -> None:
|
||||
"""All checks pass → overall 'all clear'."""
|
||||
# Create files with recent mtimes and ok content
|
||||
(tmp_path / "TASKS.md").write_text("# TASKS\n", encoding="utf-8")
|
||||
(tmp_path / "RUN_LOG.md").write_text("# RUN\n| date | pytest passed |\n", encoding="utf-8")
|
||||
|
||||
import rdb_discovery.guardrails as mod
|
||||
|
||||
old_now = mod._now
|
||||
now = datetime.now()
|
||||
|
||||
class FakePath:
|
||||
def __init__(self, path: Path):
|
||||
self._path = path
|
||||
|
||||
def exists(self) -> bool:
|
||||
return self._path.exists()
|
||||
|
||||
def stat(self):
|
||||
class StatResult:
|
||||
st_mtime = now.timestamp()
|
||||
return StatResult()
|
||||
|
||||
orig_last_modified = mod._last_modified
|
||||
|
||||
def fake_last_modified(root: Path, rel: str) -> datetime | None:
|
||||
p = root / rel
|
||||
if p.exists():
|
||||
return now
|
||||
return None
|
||||
|
||||
mod._now = lambda: now
|
||||
mod._last_modified = fake_last_modified
|
||||
|
||||
try:
|
||||
result = run_all_guardrails(tmp_path)
|
||||
# Should be clear or have a non-error overall status (guardrails may flag other things)
|
||||
assert result["overall_status"] in ("all clear", "review recommended")
|
||||
finally:
|
||||
mod._now = old_now
|
||||
mod._last_modified = orig_last_modified
|
||||
|
||||
|
||||
# -- format_report --
|
||||
|
||||
def test_format_report_includes_overall() -> None:
|
||||
results = {
|
||||
"checks": {"Test check": {"status": "ok", "details": "fine"}},
|
||||
"overall_status": "all clear",
|
||||
}
|
||||
report = format_report(results)
|
||||
assert "# Guardrail Report" in report
|
||||
assert "all clear" in report
|
||||
|
||||
|
||||
def test_format_report_with_warning() -> None:
|
||||
results = {
|
||||
"checks": {"Test check": {"status": "warning", "details": "watch out"}},
|
||||
"overall_status": "review recommended",
|
||||
}
|
||||
report = format_report(results)
|
||||
assert "review recommended" in report
|
||||
Reference in New Issue
Block a user