Files
the-nexus/scripts/validate_mempalace_taxonomy.py
Bezalel a0ee7858ff
Some checks failed
Deploy Nexus / deploy (push) Has been cancelled
feat(bezalel): MemPalace ecosystem — validation, audit, sync, auto-revert, Evennia integration
2026-04-07 14:47:12 +00:00

124 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""
Validate a wizard's mempalace.yaml against the fleet taxonomy standard.
Usage:
python validate_mempalace_taxonomy.py /path/to/mempalace.yaml
python validate_mempalace_taxonomy.py --ci /path/to/mempalace.yaml
Exit codes:
0 = valid
1 = missing required rooms or other violations
"""
import sys
from pathlib import Path
try:
import yaml
except ImportError:
print("ERROR: PyYAML not installed. Run: pip install pyyaml")
sys.exit(1)
REQUIRED_ROOMS = {
"forge",
"hermes",
"nexus",
"issues",
"experiments",
}
def load_standard():
# Try to find the fleet standard in the-nexus clone or local path
candidates = [
Path(__file__).parent.parent / "mempalace_taxonomy.yaml",
Path("/tmp/nexus_clone/docs/mempalace_taxonomy.yaml"),
Path(__file__).parent.parent.parent / "the-nexus" / "docs" / "mempalace_taxonomy.yaml",
]
for c in candidates:
if c.exists():
with open(c) as f:
return yaml.safe_load(f)
return None
def validate(path: Path):
errors = []
warnings = []
if not path.exists():
errors.append(f"File not found: {path}")
return errors, warnings
with open(path) as f:
data = yaml.safe_load(f)
if not data:
errors.append("Empty or invalid YAML")
return errors, warnings
rooms = data.get("rooms", data.get("wings", {}).get("bezalel", {}).get("rooms", []))
if isinstance(rooms, list) and rooms and isinstance(rooms[0], dict):
room_names = {r.get("name") for r in rooms if isinstance(r, dict)}
elif isinstance(rooms, dict):
room_names = set(rooms.keys())
else:
room_names = set()
missing = REQUIRED_ROOMS - room_names
if missing:
errors.append(f"Missing required rooms: {', '.join(sorted(missing))}")
# Check for duplicate room names
if len(room_names) < len(list(rooms) if isinstance(rooms, list) else rooms):
errors.append("Duplicate room names detected")
# Check for empty keywords
if isinstance(rooms, list):
for r in rooms:
if isinstance(r, dict):
kw = r.get("keywords", [])
if not kw:
warnings.append(f"Room '{r.get('name')}' has no keywords")
standard = load_standard()
if standard:
std_optional = set(standard.get("optional_rooms", {}).keys())
unknown = room_names - REQUIRED_ROOMS - std_optional
if unknown:
warnings.append(f"Non-standard rooms (OK but not in fleet spec): {', '.join(sorted(unknown))}")
return errors, warnings
def main():
import argparse
parser = argparse.ArgumentParser(description="Validate MemPalace taxonomy")
parser.add_argument("config", help="Path to mempalace.yaml")
parser.add_argument("--ci", action="store_true", help="CI mode: fail on warnings too")
args = parser.parse_args()
errors, warnings = validate(Path(args.config))
if warnings:
for w in warnings:
print(f"WARNING: {w}")
if errors:
for e in errors:
print(f"ERROR: {e}")
sys.exit(1)
if args.ci and warnings:
print("Validation failed in CI mode (warnings treated as errors)")
sys.exit(1)
print("OK: Taxonomy validation passed")
sys.exit(0)
if __name__ == "__main__":
main()