#!/usr/bin/env python3
"""
audit_identity_placeholders.py

Scans every .md file under /root/.hermes/ for bracketed placeholders
([PERSON_NAME], [ADDRESS], [PHONE], [PERSON_NAME], etc.) and reports
each occurrence with file:line + a column-1 context snippet.

This is the AUDIT step of the cleanup. It does NOT edit files.
Review the report, then apply edits manually or with a separate
script after [PERSON_NAME] approves the diff.

Rules:
  - Walks /root/.hermes/{vault,skills,profiles,work,memories}
  - Skips /root/.hermes/venv/, /root/.hermes/.hermes/, /root/.hermes/cache/
  - Skips /root/.hermes/state.db and other large binaries
  - Skips files > 1 MB (vault can grow large; we want a fast audit)
  - Reports placeholders matching the patterns observed in prior sessions:
      [PERSON_NAME], [PERSON_NAME], [NAME], [ADDRESS], [CITY],
      [PHONE], [EMAIL], [COMPANY], [AGENT], [BUSINESS]
  - Groups by placeholder type so [PERSON_NAME] can prioritize
"""

import re
import sys
from pathlib import Path

ROOT = Path("/root/.hermes")
SKIP_DIRS = {"venv", ".hermes", "cache", "image_cache", "audio_cache",
             "node_modules", "__pycache__", "gbrain", "gbrain-home",
             "SkillClaw", "skillclaw-home", "composio", "composio-home",
             "hermes-agent-src", "mirrors", "outbox", "lo-cache",
             "lo-profile", "staging", "patch-backup-0.19.0"}
MAX_FILE_BYTES = 1_048_576  # 1 MB

# Patterns observed; extend as needed. Anchored, exact-token match.
PLACEHOLDER_PATTERNS = [
    r"\[PERSON[_-]NAME\]",
    r"\[NAME\]",
    r"\[ADDRESS\]",
    r"\[CITY\]",
    r"\[PHONE\]",
    r"\[EMAIL\]",
    r"\[COMPANY\]",
    r"\[AGENT\]",
    r"\[BUSINESS\]",
    r"\[PERSON[_-]NAME\]",
]
PATTERN_RE = re.compile("|".join(PLACEHOLDER_PATTERNS))


def should_skip(path: Path) -> bool:
    parts = set(path.relative_to(ROOT).parts)
    return bool(parts & SKIP_DIRS)


def audit_file(path: Path):
    try:
        if path.stat().st_size > MAX_FILE_BYTES:
            return None
    except OSError:
        return None
    try:
        text = path.read_text(encoding="utf-8", errors="replace")
    except (OSError, UnicodeDecodeError):
        return None
    findings = []
    for i, line in enumerate(text.splitlines(), start=1):
        if PATTERN_RE.search(line):
            snippet = line.strip()[:120]
            findings.append((i, snippet))
    return findings


def main():
    by_pattern = {}
    by_file = {}
    total = 0
    for md in ROOT.rglob("*.md"):
        if should_skip(md):
            continue
        hits = audit_file(md)
        if not hits:
            continue
        rel = md.relative_to(ROOT)
        by_file[str(rel)] = hits
        for _, snippet in hits:
            for pat in PLACEHOLDER_PATTERNS:
                if re.search(pat, snippet):
                    by_pattern.setdefault(pat, []).append((str(rel), snippet))
        total += len(hits)

    print(f"Scanned /root/.hermes/ — {total} placeholder hits across {len(by_file)} files\n")

    print("=== BY FILE ===")
    for f in sorted(by_file):
        print(f"\n{f}  ({len(by_file[f])} hits)")
        for line_no, snippet in by_file[f][:5]:  # cap per-file display
            print(f"  L{line_no}: {snippet}")
        if len(by_file[f]) > 5:
            print(f"  ... +{len(by_file[f]) - 5} more")

    print("\n=== BY PATTERN ===")
    for pat, hits in sorted(by_pattern.items()):
        print(f"\n{pat}: {len(hits)} hits")
        for f, snippet in hits[:3]:
            print(f"  {f}: {snippet}")
        if len(hits) > 3:
            print(f"  ... +{len(hits) - 3} more")


if __name__ == "__main__":
    main()
