"""챕터 메타 YAML 스키마 — content/chapters/*.yaml. ending_rules의 condition은 trust_score/doubt_score 변수만 쓰는 비교식 문자열. 평가(파싱·판정)는 services/story.py의 결정적 코드가 담당한다 (LLM 판정 금지). """ from __future__ import annotations from typing import Optional from pydantic import BaseModel, ConfigDict, Field class EndingRule(BaseModel): model_config = ConfigDict(extra="forbid") id: str label: str condition: str # 예: "doubt_score >= 30" / "default" canonical: bool = False description: str = "" priority: int = 0 # 낮을수록 먼저 평가. default는 마지막 class RCardRef(BaseModel): model_config = ConfigDict(extra="forbid") id: str trigger: str # identity_direct | weapon description: str = "" class BeatRange(BaseModel): model_config = ConfigDict(extra="forbid") start: str # "E01" end: str # "E06" class Chapter(BaseModel): model_config = ConfigDict(extra="forbid") id: str title: str = "" summary: str = "" entry_beat: str # "E01-01" beat_range: BeatRange ending_rules: list[EndingRule] canon_rules: list[str] = Field(default_factory=list) r_cards: list[RCardRef] = Field(default_factory=list) pocket_max_turns: int = 6 # 개입 포켓 자유채팅 턴 상한 (강제 수렴) class ChapterFile(BaseModel): model_config = ConfigDict(extra="forbid") chapter: Chapter