Files
the-nexus/mempalace/validate_rooms.py
Claude (Opus 4.6) e957254b65
Some checks failed
Deploy Nexus / deploy (push) Has been cancelled
[claude] MemPalace × Evennia fleet memory scaffold (#1075) (#1088)
2026-04-07 14:12:38 +00:00

120 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
validate_rooms.py — Fleet palace taxonomy validator.
Checks a wizard's mempalace.yaml against the fleet standard in rooms.yaml.
Exits 0 if valid, 1 if core rooms are missing or the config is malformed.
Usage:
python mempalace/validate_rooms.py <wizard_mempalace.yaml>
python mempalace/validate_rooms.py /root/wizards/bezalel/mempalace.yaml
Refs: #1082, #1075
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
from typing import Any
try:
import yaml
except ImportError:
print("ERROR: PyYAML is required. Install with: pip install pyyaml", file=sys.stderr)
sys.exit(2)
FLEET_STANDARD = Path(__file__).parent / "rooms.yaml"
def load_yaml(path: Path) -> dict[str, Any]:
with path.open() as fh:
return yaml.safe_load(fh) or {}
def get_core_room_keys(standard: dict[str, Any]) -> list[str]:
return [r["key"] for r in standard.get("core_rooms", [])]
def get_wizard_room_keys(config: dict[str, Any]) -> list[str]:
"""Extract room keys from a wizard's mempalace.yaml.
Supports two common shapes:
rooms:
- key: forge
- key: hermes
or:
rooms:
forge: ...
hermes: ...
"""
rooms_field = config.get("rooms", {})
if isinstance(rooms_field, list):
return [r["key"] for r in rooms_field if isinstance(r, dict) and "key" in r]
if isinstance(rooms_field, dict):
return list(rooms_field.keys())
return []
def validate(wizard_config_path: Path, standard_path: Path = FLEET_STANDARD) -> list[str]:
"""Return a list of validation errors. Empty list means valid."""
errors: list[str] = []
if not standard_path.exists():
errors.append(f"Fleet standard not found: {standard_path}")
return errors
if not wizard_config_path.exists():
errors.append(f"Wizard config not found: {wizard_config_path}")
return errors
standard = load_yaml(standard_path)
config = load_yaml(wizard_config_path)
core_keys = get_core_room_keys(standard)
wizard_keys = get_wizard_room_keys(config)
missing = [k for k in core_keys if k not in wizard_keys]
for key in missing:
errors.append(f"Missing required core room: '{key}'")
return errors
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="Validate a wizard's mempalace.yaml against the fleet room standard."
)
parser.add_argument(
"config",
metavar="mempalace.yaml",
help="Path to the wizard's mempalace.yaml",
)
parser.add_argument(
"--standard",
default=str(FLEET_STANDARD),
metavar="rooms.yaml",
help="Path to the fleet rooms.yaml standard (default: mempalace/rooms.yaml)",
)
args = parser.parse_args(argv)
wizard_path = Path(args.config)
standard_path = Path(args.standard)
errors = validate(wizard_path, standard_path)
if errors:
print(f"[validate_rooms] FAIL: {wizard_path}", file=sys.stderr)
for err in errors:
print(f"{err}", file=sys.stderr)
return 1
core_count = len(get_core_room_keys(load_yaml(standard_path)))
print(f"[validate_rooms] OK: {wizard_path} — all {core_count} core rooms present.")
return 0
if __name__ == "__main__":
sys.exit(main())