OUTPUT #643 | 5292 karakter | 156 satır
========== YENİ KOMUT | 16.09.2026 16:00:40 ==========


========== YENİ KOMUT | 16.09.2026 16:00:40 ==========

#!/usr/bin/env python3
import argparse, datetime, json, os, pathlib, re, shutil, subprocess, sys

HOME = pathlib.Path("/home/hermes")
MOTION = HOME / ".hermes/shorts-motion-history.json"
CONTRACTS = HOME / ".hermes/cache/shorts-production-guard/creative-contracts"
ARCHIVES = pathlib.Path("/root/hermes-benchmark-archive")

def require_root():
    if os.geteuid() != 0:
        raise SystemExit("ERROR: root olarak çalıştır.")

def terms(a):
    out = [a.project, a.parent]
    if a.child:
        out.append(a.child)
    out += a.needle or []
    return [x for x in out if x]

def visible_hits(ts):
    pattern = "|".join(re.escape(x) for x in ts)
    p = subprocess.run(
        ["sudo","-u","hermes","rg","-l","-S",pattern,str(HOME)],
        text=True, capture_output=True
    )
    return sorted(x for x in p.stdout.splitlines() if x)

def motion_matches(project):
    if not MOTION.exists():
        return []
    d = json.loads(MOTION.read_text())
    return [x for x in d.get("entries",[]) if x.get("project") == project]

def status(a):
    project_path = pathlib.Path(a.project_path) if a.project_path else HOME / "shorts" / a.project
    contract_paths = [CONTRACTS / f"{a.parent}.json"]
    if a.child:
        contract_paths.append(CONTRACTS / f"{a.child}.json")
    hits = visible_hits(terms(a))
    mm = motion_matches(a.project)
    print("project_present=", project_path.exists())
    print("contract_present=", any(p.exists() for p in contract_paths))
    print("motion_entries=", len(mm))
    print("visible_hits=", len(hits))
    for p in hits:
        print("VISIBLE", p)
    return project_path, contract_paths, hits, mm

def archive_file(src, dst):
    dst.parent.mkdir(parents=True, exist_ok=True)
    if dst.exists():
        raise RuntimeError(f"Archive hedefi zaten var: {dst}")
    shutil.move(str(src), str(dst))

def reset(a):
    require_root()
    base = ARCHIVES / a.tag / "cleanroom"
    base.mkdir(parents=True, exist_ok=True)
    os.chmod(base, 0o700)

    project_path = pathlib.Path(a.project_path) if a.project_path else HOME / "shorts" / a.project
    if project_path.exists():
        archive_file(project_path, base / "source-project")

    for sid in [a.parent, a.child]:
        if not sid:
            continue
        p = CONTRACTS / f"{sid}.json"
        if p.exists():
            archive_file(p, base / "creative-contracts" / p.name)

    if MOTION.exists():
        d = json.loads(MOTION.read_text())
        entries = d.get("entries", [])
        kept = [x for x in entries if x.get("project") != a.project]
        removed = len(entries) - len(kept)
        if removed:
            backup = base / "shorts-motion-history.pre-cleanroom.json"
            if not backup.exists():
                shutil.copy2(MOTION, backup)
            d["entries"] = kept
            tmp = MOTION.with_suffix(".tmp")
            tmp.write_text(json.dumps(d, ensure_ascii=False, indent=2) + "\n")
            os.replace(tmp, MOTION)

    forensic_patterns = [
        "HERMES_*HISTORY*.json",
        "HERMES_*AUDIT*.json",
        "HERMES_*INVENTORY*.json",
        "HERMES_*PERFORMANCE*.json",
    ]
    rx = re.compile("|".join(re.escape(x) for x in terms(a)), re.I)
    moved = set()
    for pat in forensic_patterns:
        for p in HOME.glob(pat):
            if p in moved or not p.is_file():
                continue
            try:
                text = p.read_text(errors="ignore")
            except Exception:
                continue
            if rx.search(text):
                archive_file(p, base / "forensic" / p.name)
                moved.add(p)

    meta = {
        "tag": a.tag,
        "project": a.project,
        "parent": a.parent,
        "child": a.child,
        "needles": a.needle or [],
        "cleaned_at_utc": datetime.datetime.now(datetime.timezone.utc).isoformat(),
    }
    (base / "cleanroom.json").write_text(
        json.dumps(meta, ensure_ascii=False, indent=2) + "\n"
    )

def verify(a):
    _, _, hits, mm = status(a)
    project_exists = (pathlib.Path(a.project_path) if a.project_path else HOME / "shorts" / a.project).exists()
    contract_exists = any(
        (CONTRACTS / f"{sid}.json").exists()
        for sid in [a.parent, a.child] if sid
    )
    ok = not project_exists and not contract_exists and not mm and not hits
    print("CLEANROOM=", "PASS" if ok else "FAIL")
    return ok

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("action", choices=["audit","reset","verify"])
    ap.add_argument("--tag", required=True)
    ap.add_argument("--project", required=True)
    ap.add_argument("--project-path")
    ap.add_argument("--parent", required=True)
    ap.add_argument("--child")
    ap.add_argument("--needle", action="append")
    a = ap.parse_args()

    if a.action == "audit":
        status(a)
    elif a.action == "reset":
        reset(a)
        sys.exit(0 if verify(a) else 2)
    else:
        sys.exit(0 if verify(a) else 2)

if __name__ == "__main__":
    main()
root@213-238-170-219:~#