diff --git a/docs/robots.txt b/docs/robots.txt
index 72c9406..a5e6789 100644
--- a/docs/robots.txt
+++ b/docs/robots.txt
@@ -1,3 +1,3 @@
User-agent: *
Allow: /
-Sitemap: https://modimihir07.github.io/agentic-os/sitemap.xml
+Sitemap: https://zumayaaustin-creator.github.io/agentic-os/sitemap.xml
diff --git a/scripts/integrity_check.py b/scripts/integrity_check.py
new file mode 100644
index 0000000..23829de
--- /dev/null
+++ b/scripts/integrity_check.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python3
+"""
+Agentic-OS Codebase Integrity Check (run hourly via cron)
+
+Detects STALE state in the codebase — references that contradict the
+single source of truth:
+
+ SOURCE OF TRUTH
+ - dashboard port ........ data/settings.json -> dashboard.port (currently 8080)
+ - canonical repo ........ github.com/zumayaaustin-creator/agentic-os
+ - canonical location .... /home/austin/agentic-os
+ - terminal endpoint ..... /ws/terminal on the MAIN port (NOT a separate 8082)
+
+Any contradiction of the above is reported as a finding. This script is
+read-only: it never edits files. It prints a report and exits 0 if clean,
+1 if any finding, 2 on a check error (so the cron can alert).
+
+Run: python3 scripts/integrity_check.py
+"""
+import json
+import re
+import sys
+from pathlib import Path
+
+BASE = Path(__file__).resolve().parent.parent
+SETTINGS = BASE / "data" / "settings.json"
+
+# ── Source of truth ────────────────────────────────────────────────
+TRUTH = {
+ "expected_port": 8080, # overwritten below from settings.json if present
+ "canonical_repo": "zumayaaustin-creator/agentic-os",
+ "canonical_location": "/home/austin/agentic-os",
+ "terminal_endpoint": "/ws/terminal",
+}
+STALE_PATTERNS = [
+ (r"modimihir07", "stale GitHub repo (should be zumayaaustin-creator/agentic-os)"),
+ (r"Desktop/Agentic\s*OS\s*Project", "stale project location (should be /home/austin/agentic-os)"),
+ (r"127\.0\.0\.1:8082", "dead port 8082 referenced (terminal consolidated to /ws/terminal on main port)"),
+ (r"port\s*8082", "dead port 8082 referenced"),
+ (r":8081", "stale port 8081 referenced as the server/terminal port"),
+ (r"wsPort\s*=\s*8082", "terminal.js still targets dead 8082"),
+ (r"action:\s*'(input|resize|output)'", "terminal.js uses wrong 'action:' protocol (backend expects 'type:')"),
+]
+# Files to skip (build artifacts, venv, node_modules)
+SKIP_DIRS = {"venv", "node_modules", "__pycache__", ".git", "graphify-out"}
+SKIP_EXT = {".pyc"}
+
+findings = []
+
+
+def add(file, line_no, detail, excerpt):
+ findings.append(f"[{file}:{line_no}] {detail}\n > {excerpt.strip()[:120]}")
+
+
+def load_truth():
+ if SETTINGS.exists():
+ try:
+ s = json.loads(SETTINGS.read_text(encoding="utf-8"))
+ p = int(s.get("dashboard", {}).get("port", 8080))
+ TRUTH["expected_port"] = p
+ except Exception:
+ pass
+
+
+def scan_text_files():
+ for p in BASE.rglob("*"):
+ if not p.is_file():
+ continue
+ if any(part in SKIP_DIRS for part in p.relative_to(BASE).parts):
+ continue
+ if p.name == "integrity_check.py":
+ continue # don't flag our own pattern strings
+ # only scan text-like files
+ if p.suffix.lower() not in {
+ ".md", ".py", ".js", ".ts", ".html", ".json", ".sh", ".yml", ".yaml", ".toml", ".ini", ".txt"
+ }:
+ continue
+ try:
+ text = p.read_text(encoding="utf-8", errors="ignore")
+ except Exception:
+ continue
+ rel = p.relative_to(BASE)
+ for pat, desc in STALE_PATTERNS:
+ for m in re.finditer(pat, text, re.IGNORECASE):
+ # find line number
+ line_no = text.count("\n", 0, m.start()) + 1
+ excerpt = text.splitlines()[line_no - 1] if line_no <= len(text.splitlines()) else ""
+ add(str(rel), line_no, desc, excerpt)
+
+
+def check_live_server():
+ """Confirm the running server is on the expected port and serving."""
+ import urllib.request
+ port = TRUTH["expected_port"]
+ url = f"http://127.0.0.1:{port}/"
+ try:
+ with urllib.request.urlopen(url, timeout=4) as r:
+ if r.status != 200:
+ findings.append(f"[LIVE] server on :{port} returned HTTP {r.status} (expected 200)")
+ except Exception as e:
+ findings.append(f"[LIVE] server NOT reachable on :{port} ({type(e).__name__}: {e})")
+
+
+def check_terminal_endpoint():
+ """The terminal page must reference /ws/terminal and the main host."""
+ tjs = BASE / "dashboard" / "pages" / "terminal.js"
+ if not tjs.exists():
+ findings.append("[terminal.js] file missing — Terminal page broken")
+ return
+ txt = tjs.read_text(encoding="utf-8", errors="ignore")
+ if "/ws/terminal" not in txt:
+ findings.append("[terminal.js] does NOT connect to /ws/terminal (terminal disconnected from OS)")
+ if "wsPort" in txt or ":8082" in txt or "port 8082" in txt:
+ findings.append("[terminal.js] still references dead 8082 port")
+
+
+def check_agent_enabled():
+ """opencode should be enabled (it is the code/DevOps agent)."""
+ if not SETTINGS.exists():
+ return
+ try:
+ s = json.loads(SETTINGS.read_text(encoding="utf-8"))
+ oc = s.get("agent_preferences", {}).get("opencode", {})
+ if oc.get("enabled") is not True:
+ findings.append(f"[settings.json] opencode.enabled={oc.get('enabled')!r} (expected true)")
+ except Exception:
+ pass
+
+
+def main():
+ load_truth()
+ scan_text_files()
+ check_terminal_endpoint()
+ check_agent_enabled()
+ check_live_server()
+
+ print("=" * 64)
+ print(" Agentic-OS Integrity Check")
+ print(f" port(source of truth) = {TRUTH['expected_port']}")
+ print("=" * 64)
+ if not findings:
+ print(" ✓ CLEAN — no stale references detected.")
+ return 0
+ print(f" ✗ {len(findings)} FINDING(S):\n")
+ for f in findings:
+ print(" - " + f)
+ print()
+ return 1
+
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except Exception as e:
+ print(f"CHECK ERROR: {type(e).__name__}: {e}")
+ sys.exit(2)
diff --git a/server.py b/server.py
index f606b3f..54cc45a 100644
--- a/server.py
+++ b/server.py
@@ -2517,8 +2517,7 @@ import signal
# NOTE: The interactive terminal is provided by the in-app WebSocket
# endpoint `/ws/terminal` (see PtySession above). The previous standalone
-# WebSocket terminal server on port 8082 was removed to avoid two
-# redundant terminal implementations.
+# terminal process was removed to avoid two redundant terminal implementations.