Kansho/backend/journal_policy.py
2026-08-25 13:57:23 +02:00

52 lines
1.7 KiB
Python

"""Small write/decision boundary for the journal MVP. Not a policy engine."""
from __future__ import annotations
from conversation_signals import similar_enough
class PolicyError(Exception):
def __init__(self, code: str, message: str, status_code: int = 400):
super().__init__(message)
self.code = code
self.message = message
self.status_code = status_code
ENTRY_ORIGINS = {"user_edit", "accepted_draft", "restore"}
def require_explicit_generate(explicit: bool) -> None:
if not explicit:
raise PolicyError("generate_not_explicit", "Journal Drafts entstehen nur auf ausdrückliche Aktion.")
def consolidation_offer(conversations: list[dict] | int) -> bool:
"""Offer merge only when conversations look narratively compatible. User decides."""
if isinstance(conversations, int):
return False
return similar_enough(conversations)
def source_conversation_ids(explicit_ids: list[str] | None, day_conversation_ids: list[str]) -> list[str]:
"""Missing selection never silently merges multiple conversations."""
known = [item for item in day_conversation_ids if item]
if explicit_ids:
chosen = [item for item in explicit_ids if item in known]
if not chosen:
raise PolicyError("unknown_conversation", "Keine der angegebenen Conversations gehört zu diesem Tag.")
return chosen
if not known:
raise PolicyError("no_source_dialogue", "Ohne Dialog gibt es nichts zu erzeugen.")
return [known[-1]]
def draft_must_not_touch_entry() -> None:
return None
def require_origin(origin: str) -> str:
if origin not in ENTRY_ORIGINS:
raise PolicyError("invalid_origin", "origin muss user_edit, accepted_draft oder restore sein")
return origin