Files
natiris/core/LogicValidator.py

123 lines
3.6 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
LogicValidator prüft Core-Logik für Konsistenz, Boundaries, Transitionen
"""
import json
import os
import sys
from datetime import datetime, timezone
PATHS = {
"state": os.path.expanduser("~/natiris/core/natiris_full_state.json"),
"config": os.path.expanduser("~/natiris/config/character_genesis.json"),
"output": os.path.expanduser("~/natiris/core/logic_validation.json"),
}
def clamp(val, lo=0.0, hi=10.0):
return max(lo, min(hi, float(val)))
def clamp01(val):
return max(0.0, min(1.0, float(val)))
def validate(state, config):
errors = []
warnings = []
# Core-Values bounds
core = state.get("core_state", {})
emotion = state.get("modules", {}).get("Emotion", {})
maturity = state.get("modules", {}).get("Maturity", {})
bond = state.get("modules", {}).get("Bond", {})
# 1. Mood bounds
if not (0 <= core.get("mood", 5) <= 10):
errors.append("mood außerhalb 0-10")
# 2. loneliness bounds
if not (0 <= core.get("loneliness", 2) <= 10):
errors.append("loneliness außerhalb 0-10")
# 3. Bond-Logik
if bond.get("exclusivity_active") and bond.get("bonded_to") is None:
errors.append("exclusivity ohne bonded_to")
if bond.get("bonded_to") and not bond.get("exclusivity_active"):
warnings.append("bonded_to ohne exclusivity nicht notwendig, möglicherweise gewünscht")
# 4. Maturity Bias bounds
if not (0 <= maturity.get("stability_bias", 0) <= 1):
errors.append("stability_bias außerhalb 0-1")
if not (0 <= maturity.get("dependency_bias", 0) <= 1):
errors.append("dependency_bias außerhalb 0-1")
# 5. Regression Factor
if not (0 <= maturity.get("regression_factor", 0) <= 1):
errors.append("regression_factor außerhalb 0-1")
# 6. Bond-Jealousy-Risk
if not (0 <= bond.get("jealousy_risk", 0) <= 1):
errors.append("jealousy_risk außerhalb 0-1")
return errors, warnings
def test_transitions(state, config):
tests = []
# Simulation: loneliness hoch → mood sinkt
test_state = state.copy()
test_state["core_state"] = state.get("core_state", {}).copy()
test_state["core_state"]["loneliness"] = 8
test_state["modules"] = state.get("modules", {}).copy()
test_state["modules"]["Emotion"] = state.get("modules", {}).get("Emotion", {}).copy()
# mood_delta sollte sinken wenn loneliness hoch
mood_delta_bound = clamp((test_state["core_state"]["loneliness"] - 5) * -0.1)
if mood_delta_bound < -0.2:
tests.append("✅ Loneliness-Test (hoch → mood sinkt)")
# Bond-Test
if test_state["modules"].get("Bond", {}).get("exclusivity_active"):
tests.append("✅ Bond-Test (exklusiv aktiv)")
return tests
def main():
try:
with open(PATHS["state"]) as f:
state = json.load(f)
except Exception as e:
print(f"❌ State nicht ladbar: {e}")
sys.exit(1)
with open(PATHS["config"]) as f:
config = json.load(f)
errors, warnings = validate(state, config)
tests = test_transitions(state, config)
if errors:
for e in errors:
print(f"{e}")
else:
print("✅ Alle Bounds OK")
if warnings:
for w in warnings:
print(f"⚠️ {w}")
for t in tests:
print(t)
result = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"errors": errors,
"warnings": warnings,
"tests_passed": tests
}
with open(PATHS["output"], "w") as f:
json.dump(result, f, indent=2)
if __name__ == "__main__":
main()