104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
# SPDX-FileCopyrightText: 2026 Art Sea LLC
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
|
|
from band_aider.ai_client.human_feedback_store import HumanFeedbackStore
|
|
from band_aider.ui.dto.human_feedback import HumanFeedbackDTO, HumanFeedbackKind
|
|
from tests.support.memory_repo_exec import MemoryRepoExec
|
|
|
|
|
|
def test_human_feedback_store_persists_cycle_records_and_repeat_counts() -> None:
|
|
"""Verify cycle persistence uses the explicit in-memory repository boundary."""
|
|
|
|
adapter = MemoryRepoExec()
|
|
store = HumanFeedbackStore(adapter.root, repo_exec=adapter)
|
|
|
|
first = store.record_cycle(
|
|
request_md5=hashlib.md5(b"prompt").hexdigest(),
|
|
response_md5=hashlib.md5(b"same").hexdigest(),
|
|
response_tail="same",
|
|
model="local",
|
|
)
|
|
second = store.record_cycle(
|
|
request_md5=hashlib.md5(b"prompt").hexdigest(),
|
|
response_md5=hashlib.md5(b"same").hexdigest(),
|
|
response_tail="same",
|
|
model="local",
|
|
)
|
|
|
|
assert first.repeat_count == 1
|
|
assert second.repeat_count == 2
|
|
assert store.latest_cycle_record(first.request_md5) == second
|
|
|
|
|
|
def test_human_feedback_store_returns_last_non_expired_feedback() -> None:
|
|
"""Verify stationary feedback records select the latest non-expired decision."""
|
|
|
|
now = 1000.0
|
|
adapter = MemoryRepoExec()
|
|
store = HumanFeedbackStore(adapter.root, clock=lambda: now, repo_exec=adapter)
|
|
request_id = "a:b"
|
|
store.record_feedback(
|
|
HumanFeedbackDTO(
|
|
request_id=request_id,
|
|
request_md5="a",
|
|
response_md5="b",
|
|
kind=HumanFeedbackKind.Ignore,
|
|
reason="policy",
|
|
source_guidance="text",
|
|
source_action="resend",
|
|
recorded_at=0.0,
|
|
expires_at=1.0,
|
|
)
|
|
)
|
|
store.record_feedback(
|
|
HumanFeedbackDTO(
|
|
request_id=request_id,
|
|
request_md5="a",
|
|
response_md5="b",
|
|
kind=HumanFeedbackKind.Advice,
|
|
reason="policy",
|
|
source_guidance="text",
|
|
source_action="resend",
|
|
advice="use readonly files",
|
|
recorded_at=500.0,
|
|
expires_at=2000.0,
|
|
)
|
|
)
|
|
|
|
latest = store.latest_feedback(request_id)
|
|
|
|
assert latest is not None
|
|
assert latest.kind is HumanFeedbackKind.Advice
|
|
assert latest.advice == "use readonly files"
|
|
|
|
|
|
def test_human_feedback_store_tracks_advice_application() -> None:
|
|
"""Verify advice application updates the durable in-memory feedback record."""
|
|
|
|
adapter = MemoryRepoExec()
|
|
store = HumanFeedbackStore(adapter.root, clock=lambda: 42.0, repo_exec=adapter)
|
|
feedback = HumanFeedbackDTO(
|
|
request_id="a:b",
|
|
request_md5="a",
|
|
response_md5="b",
|
|
kind=HumanFeedbackKind.Advice,
|
|
reason="redirect",
|
|
source_guidance="do not add more files",
|
|
source_action="resend",
|
|
advice="do not add more files",
|
|
recorded_at=10.0,
|
|
expires_at=3700.0,
|
|
)
|
|
store.record_feedback(feedback)
|
|
|
|
updated = store.mark_applied("a:b", "derived")
|
|
|
|
assert updated is not None
|
|
assert updated.application_count == 1
|
|
assert updated.last_applied_at == 42.0
|
|
assert updated.last_applied_request_md5 == "derived"
|