Files
brain-of-reese/tests/unit/test_prompts.py
T

119 lines
4.7 KiB
Python

"""Unit: locked persona prompt builder (PLAN §6 verbatim + both modes)."""
from __future__ import annotations
import uuid
import pytest
from app.models import Document
from app.rag.prompts import PERSONA, _base, build_deflect_prompt, build_high_prompt
def _doc(path: str, content: str, title: str) -> Document:
return Document(
id=uuid.uuid4(),
source="Homelab",
path=path,
full_path=f"/tmp/{path}",
title=title,
content=content,
content_hash="0" * 64,
)
def test_persona_rules_present_verbatim() -> None:
# Aligned to the owner's working-tree persona edits (PLAN §6 revision,
# 2026-08-22): no "you've got this" tagline, no mandated deflection
# opening. The honesty gate itself (rule 3) is unchanged.
for fragment in (
'You are "Brain of Reese" — the digital brain of Reese, a self-hoster and',
"optimistic about the user's ability to do things",
"Answer ONLY from the provided document context. Cite which document(s)",
"you used, by path.",
"Be concrete: names, versions, ports, hosts, schedules",
'HONESTY GATE: if <relevance> is "LOW", you must NOT pretend to know',
"Offer 2-3 alternative questions about things you DO have notes on.",
"Never invent facts, hosts, or steps that are not in the context.",
"Keep answers tight: short paragraphs, bullets where helpful.",
):
assert fragment in PERSONA
def test_persona_owner_edits_are_preserved() -> None:
"""PLAN §6 revision (2026-08-22): the removed elements must stay out."""
assert 'you\'ve got this' not in PERSONA # tagline removed by the owner
assert "Start your answer with a variant of" not in PERSONA # no mandated opening
assert "HONESTY GATE" in PERSONA # the gate itself is intact
def test_high_prompt_carries_relevance_marker_and_full_documents() -> None:
doc = _doc("kubernetes.md", "Talos Linux on three nodes.", "Kubernetes Homelab Cluster")
prompt = build_high_prompt([doc])
assert "<relevance>HIGH</relevance>" in prompt
assert "DEFLECT_MODE" not in prompt
assert "<documents>" in prompt and "</documents>" in prompt
assert 'path="kubernetes.md"' in prompt
assert "Talos Linux on three nodes." in prompt
assert "HONESTY GATE" in prompt # persona intact
def test_high_prompt_lists_multiple_documents_in_order() -> None:
a = _doc("a.md", "CONTENT_A", "Title A")
b = _doc("b.md", "CONTENT_B", "Title B")
prompt = build_high_prompt([a, b])
assert prompt.index("CONTENT_A") < prompt.index("CONTENT_B")
assert 'title="Title B"' in prompt
def test_high_prompt_without_documents_stays_honest() -> None:
prompt = build_high_prompt([])
assert "<documents>" in prompt
assert "do not invent specifics" in prompt
def test_low_prompt_has_deflect_mode_and_titles_only() -> None:
titles = ["Kubernetes Homelab Cluster", "Backup Strategy"]
prompt = build_deflect_prompt(titles)
assert "<relevance>LOW</relevance>" in prompt
assert "DEFLECT_MODE" in prompt # marker the E2E mock keys on
assert "- Kubernetes Homelab Cluster" in prompt
assert "- Backup Strategy" in prompt
def test_low_prompt_never_contains_document_content() -> None:
secret = "SECRET_DOCUMENT_CONTENT_12345"
prompt = build_deflect_prompt(["Some Title"])
assert secret not in prompt
assert "<documents>" not in prompt
assert "HONESTY GATE" in prompt # the LOW rule is what the model must follow
def test_low_prompt_with_no_titles() -> None:
assert "nothing close at all" in build_deflect_prompt([])
def test_zero_note_prompt_is_byte_identical_to_pre_steering() -> None:
"""Phase 15 contract: with no steering notes the prompt is exactly what
it was before the <tuning> section existed."""
doc = _doc("kubernetes.md", "Talos Linux on three nodes.", "Kubernetes Homelab Cluster")
block = (
'<document source="Homelab" path="kubernetes.md" title="Kubernetes Homelab Cluster">\n'
"Talos Linux on three nodes.\n"
"</document>"
)
assert build_high_prompt([doc]) == _base("HIGH") + "\n<documents>\n" + block + "\n</documents>"
assert build_deflect_prompt(["T1", "T2"]) == (
_base("LOW")
+ "\nDEFLECT_MODE: retrieval was weak — the titles below are the closest "
"your notes come to the question. They are titles only; do not pretend "
"they answer it. Use them to propose 2-3 alternative questions.\n"
+ "- T1\n- T2"
)
assert "<tuning>" not in build_high_prompt([doc])
assert "<tuning>" not in build_deflect_prompt([])
def test_relevance_placeholder_rejected_for_garbage() -> None:
with pytest.raises(ValueError, match="HIGH or LOW"):
_base("MEDIUM")