========== 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:~#