"""Shared enumerations for Case Zero schemas. These constrain the *shape* of a case (so it stays solvable and the grammars stay small). The model still invents all creative content - names, motives, prose, and the specific clues - freely within these buckets. """ from __future__ import annotations from enum import StrEnum class Difficulty(StrEnum): GENTLE = "gentle" STANDARD = "standard" HARD = "hard" FIENDISH = "fiendish" class CrimeKind(StrEnum): """What kind of case this is. The structure (one culprit, a false alibi broken by physical evidence, innocents with unrelated secrets) is identical for every kind; only the story the fields tell changes. HOMICIDE stays the default so every existing case file loads unchanged.""" HOMICIDE = "homicide" THEFT = "theft" FRAUD = "fraud" BLACKMAIL = "blackmail" ARSON = "arson" MISSING = "missing_person" CON = "con" POISONING = "poisoning" RANSOM = "ransom" SABOTAGE = "sabotage" class DiscoveryMethod(StrEnum): """How a clue can be obtained. Non-INTERROGATION methods guarantee a clue is reachable even if no suspect ever volunteers it (the discoverability gate).""" SEARCH = "search" INTERROGATION = "interrogation" FORENSIC = "forensic" DOCUMENT = "document" class MotiveCategory(StrEnum): GREED = "greed" REVENGE = "revenge" JEALOUSY = "jealousy" FEAR = "fear" AMBITION = "ambition" LOVE = "love" CONCEALMENT = "concealment" LOYALTY = "loyalty" class Intent(StrEnum): """The suspect's chosen posture for a single turn (advisory, model-reported).""" COOPERATE = "cooperate" DEFLECT = "deflect" DENY = "deny" VOLUNTEER = "volunteer" BREAK_DOWN = "break_down" class EvidenceReaction(StrEnum): """How the suspect reacts when shown evidence (advisory, model-reported).""" NONE = "none" DEFLECT = "deflect" PANIC = "panic" CONCEDE = "concede" class Relevance(StrEnum): """Deterministic relevance of presented evidence to a suspect's dossier. Computed by the engine (never the model). ``BREAKING`` means the evidence is listed in one of the suspect's ``AnchoredLie.breaks_on`` sets. """ NONE = "none" TANGENTIAL = "tangential" DIRECT = "direct" BREAKING = "breaking" class SubjectType(StrEnum): SUSPECT = "suspect" SCENE = "scene" PROP = "prop"