| 387 | self._cleanup() |
| 388 | |
| 389 | def record_feedback( |
| 390 | self, |
| 391 | request_id: str, |
| 392 | *, |
| 393 | signal: str, |
| 394 | ok: bool, |
| 395 | action: str, |
| 396 | from_tier: str = "", |
| 397 | to_tier: str = "", |
| 398 | reason: str = "", |
| 399 | ) -> bool: |
| 400 | now = self._now() |
| 401 | # Apply to in-memory state. |
| 402 | applied = False |
| 403 | for record in reversed(self._records): |
| 404 | if record.request_id != request_id: |
| 405 | continue |
| 406 | record.feedback_signal = signal |
| 407 | record.feedback_ok = ok |
| 408 | record.feedback_action = action |
| 409 | record.feedback_from_tier = _normalize_tier_label(from_tier) if from_tier else "" |
| 410 | record.feedback_to_tier = _normalize_tier_label(to_tier) if to_tier else "" |
| 411 | record.feedback_reason = reason |
| 412 | record.feedback_submitted_at = now |
| 413 | applied = True |
| 414 | break |
| 415 | # Persist as event so future loads reconstruct state. |
| 416 | try: |
| 417 | self._storage.append({ |
| 418 | "type": "feedback", |
| 419 | "request_id": request_id, |
| 420 | "timestamp": now, |
| 421 | "feedback_signal": signal, |
| 422 | "feedback_ok": bool(ok), |
| 423 | "feedback_action": action, |
| 424 | "feedback_from_tier": _normalize_tier_label(from_tier) if from_tier else "", |
| 425 | "feedback_to_tier": _normalize_tier_label(to_tier) if to_tier else "", |
| 426 | "feedback_reason": reason, |
| 427 | "feedback_submitted_at": now, |
| 428 | }) |
| 429 | except Exception: |
| 430 | pass |
| 431 | return applied |
| 432 | |
| 433 | def reset(self) -> None: |
| 434 | self._records.clear() |