{"repo": "bali-zero/teman2", "files": {"agent-library/scar_replay/world-scan-run.sh": {"9e8bb6055c42e72817fc7b01bc5035a2a7b7bf41": {"t": 1785745959.425854, "n": 8335, "h": "1d26bad6606b7ab9", "c": "#!/bin/bash\n# world-scan-run.sh — weekly external failure-pattern scan for the evolver.\n#\n# Reuse-first (2026-06-04): forked from ~/scripts/wr2-external-bench-run.sh.\n# ~80% reused (multi-LLM ingest+extract via a Claude agent, DeepSeek translate\n# via world_scan_translate.py, devils-advocate-style gate built into the\n# translator's deterministic grade, _proposed/ staging, Telegram). The only NEW\n# code is world_scan_translate.py (pattern -> draft executable probe).\n#\n# Pipeline:\n# 1. INGEST+EXTRACT (Claude Opus agent w/ web search): scan SRE/security/\n# agent-failure sources -> JSON list of failure patterns.\n# 2. TRANSLATE (world_scan_translate.py + DeepSeek): each pattern -> draft probe\n# with a DETERMINISTIC executability gate (ADOPT/OBSERVE/REJECT).\n# 3. STAGE: write drafts to research/operations/_proposed/-world-scan.md.\n# 4. NOTIFY: Telegram summary to Antonello. NEVER auto-merge; human promotes\n# an ADOPT draft into scar_probes.py by hand.\n#\n# Cron: weekly (1st-of-week guard inside). Schedule via LaunchAgent.\n# Cost: ~$0.05/week (Gemini/Claude OAuth + DeepSeek translate calls).\n\nset -euo pipefail\n\nLOGDIR=\"${HOME}/logs\"; mkdir -p \"$LOGDIR\"\nLOG=\"$LOGDIR/world-scan.log\"\nERR=\"$LOGDIR/world-scan.err.log\"\n\nHARNESS_DIR=\"${SCAR_REPLAY_DIR:-${HOME}/nuzantara-deploy/agent-library/scar_replay}\"\nREPO_ROOT=\"${WORLD_SCAN_REPO_ROOT:-${HOME}/nuzantara-deploy}\"\nWEEK_TAG=\"$(date +%Y-W%V)\"\nPROPOSED_DIR=\"${REPO_ROOT}/research/operations/_proposed\"\nOUTPUT_FILE=\"${PROPOSED_DIR}/${WEEK_TAG}-world-scan-probes.md\"\nPATTERNS_JSON=\"/tmp/world-scan-patterns-${WEEK_TAG}.json\"\n\nlog() { echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*\" >> \"$LOG\"; }\n\n# telegram_alert: reused verbatim from scar-replay-run.sh (#1090). Resolves token\n# + chat id from sanctioned vaults; tolerates OWNER vs APPROVAL chat-id naming\n# drift; suppresses silently if creds unresolved (Law 4 — never block on outage).\ntelegram_alert() {\n local msg=\"$1\"\n local tok=\"${TELEGRAM_BOT_TOKEN:-}\"\n local chat=\"${TELEGRAM_OWNER_CHAT_ID:-${TELEGRAM_APPROVAL_CHAT_ID:-}}\"\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [[ -f \"$f\" ]] || continue\n [[ -z \"${tok}\" ]] && tok=\"$(grep -m1 -E '^TELEGRAM_BOT_TOKEN=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n [[ -z \"${chat}\" ]] && chat=\"$(grep -m1 -E '^TELEGRAM_(OWNER|APPROVAL)_CHAT_ID=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n done\n fi\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n log \"WARN: telegram creds unresolved — human-alert suppressed: ${msg}\"\n return 0\n fi\n curl -sS --max-time 20 -X POST \"https://api.telegram.org/bot${tok}/sendMessage\" \\\n -d \"chat_id=${chat}\" -d \"text=${msg}\" >/dev/null 2>&1 || true\n}\n\nlog \"world-scan starting (week=${WEEK_TAG}, out=${OUTPUT_FILE})\"\n\n# --- idempotence: one scan per week ---\nif [ -s \"$OUTPUT_FILE\" ]; then\n log \"skip: ${OUTPUT_FILE} already exists ($(wc -l < \"$OUTPUT_FILE\") lines). Delete to re-run.\"\n exit 0\nfi\n\n# --- worktree-isolation guard (same discipline as scar-replay-run.sh): never\n# run from inside the shared deploy worktree ---\ncase \"$(pwd -P)/\" in\n \"${REPO_ROOT}/\"*) log \"REFUSE: cwd inside shared deploy worktree; aborting.\"; exit 0 ;;\nesac\n\n# --- secrets: DEEPSEEK_API_KEY (with vault drift fallback) + telegram ---\nDS_KEY=\"${DEEPSEEK_API_KEY:-}\"\nif [ -z \"$DS_KEY\" ]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [ -f \"$f\" ] || continue\n line=$(grep -m1 -E '^DEEPSEEK_API_KEY=' \"$f\" 2>/dev/null || true)\n [ -n \"$line\" ] && { DS_KEY=\"${line#DEEPSEEK_API_KEY=}\"; DS_KEY=\"${DS_KEY%\\\"}\"; DS_KEY=\"${DS_KEY#\\\"}\"; break; }\n done\nfi\nif [ -z \"$DS_KEY\" ]; then\n log \"FATAL: DEEPSEEK_API_KEY not found in any vault — cannot translate. Aborting.\"\n exit 2\nfi\nexport DEEPSEEK_API_KEY=\"$DS_KEY\"\n\nmkdir -p \"$PROPOSED_DIR\"\n\n# --- Step 1: INGEST + EXTRACT via Claude Opus agent (OAuth-only, web search) ---\n# Reuse of the wr2-external-bench invocation shape. The agent does the web\n# research and emits a strict JSON array of failure patterns to PATTERNS_JSON.\nINGEST_PROMPT=\"You are world-scan, the evolver's external research scout.\n\nResearch the LAST ~30 days of public best-practices and post-mortems on:\n - SRE / reliability engineering (toil, retries, idempotency, locking, queues)\n - chaos engineering & fault injection\n - autonomous-agent / LLM-agent failure modes (loops, drift, tool misuse, state)\n - CI/CD & git-worktree / deploy hazards\nUse web search. Prefer concrete engineering write-ups (incident reports, SRE\nbooks/blogs, postmortems), NOT listicles.\n\nExtract 6-12 DISTINCT failure patterns relevant to a self-improving ops agent\nthat runs local git worktrees, LaunchAgent cron, shell scripts, Postgres.\n\nWrite ONLY a strict JSON array to ${PATTERNS_JSON}, each item:\n {\\\"title\\\": \\\"...\\\", \\\"text\\\": \\\"2-4 sentence description of the failure mode and why it bites\\\", \\\"source\\\": \\\"url or outlet\\\"}\nNo prose around the JSON. Reject vague/cultural advice — only concrete, testable failure mechanics.\"\n\nCLAUDE_BIN=\"${HOME}/.local/bin/claude\"; [ -x \"$CLAUDE_BIN\" ] || CLAUDE_BIN=\"/opt/homebrew/bin/claude\"\n\nlog \"step1: ingest+extract via claude opus (web search)\"\ntimeout 1800 \"$CLAUDE_BIN\" -p \\\n --model claude-opus-4-8 \\\n --permission-mode bypassPermissions \\\n --max-budget-usd \"${WORLD_SCAN_MAX_BUDGET_USD:-5}\" \\\n \"$INGEST_PROMPT\" >> \"$LOG\" 2>> \"$ERR\" || log \"WARN: ingest agent exit=$?\"\n\nif [ ! -s \"$PATTERNS_JSON\" ]; then\n log \"FATAL: no patterns JSON produced at ${PATTERNS_JSON}. Aborting.\"\n # Telegram: this needs a human (ingest produced nothing).\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: ingest produced no patterns. Check ${ERR}.\"\n exit 3\nfi\nlog \"step1 done: $(wc -c < \"$PATTERNS_JSON\") bytes of patterns\"\n\n# --- Step 2+3: TRANSLATE each pattern + STAGE drafts ---\nlog \"step2: translate patterns -> draft probes (DeepSeek + deterministic gate)\"\nPYTHONPATH=\"${HARNESS_DIR}\" python3 - \"$PATTERNS_JSON\" \"$OUTPUT_FILE\" \"$WEEK_TAG\" <<'PYEOF' >> \"$LOG\" 2>> \"$ERR\"\nimport json, sys, os, datetime\nsys.path.insert(0, os.environ[\"PYTHONPATH\"])\nimport world_scan_translate as wt\n\npatterns_path, out_path, week = sys.argv[1], sys.argv[2], sys.argv[3]\nkey = os.environ[\"DEEPSEEK_API_KEY\"]\npatterns = json.load(open(patterns_path))\nif not isinstance(patterns, list):\n print(\"patterns JSON is not a list — abort\"); sys.exit(4)\n\ndrafts = []\nfor p in patterns:\n title = (p.get(\"title\") or \"untitled\").strip()\n text = (p.get(\"text\") or \"\") + \"\\nSource: \" + (p.get(\"source\") or \"\")\n d = wt.translate_pattern(key, title, text)\n d.source_refs = p.get(\"source\") or title\n drafts.append(d)\n\nadopt = [d for d in drafts if d.category == \"ADOPT\"]\nobserve = [d for d in drafts if d.category == \"OBSERVE\"]\nreject = [d for d in drafts if d.category == \"REJECT\"]\n\nheader = (\n f\"# World-Scan draft probes — {week}\\n\\n\"\n f\"> Auto-generated by world-scan (reuse-first fork of wr2-external-bench). \"\n f\"These are DRAFT replay-probes proposed from external failure patterns. \"\n f\"**Nothing here is live.** A human promotes an ADOPT draft into \"\n f\"`agent-library/scar_replay/scar_probes.py` by hand (fixture + assertion as \"\n f\"code) and commits it. Never auto-merged (Law 5).\\n\\n\"\n f\"**Summary:** {len(adopt)} ADOPT · {len(observe)} OBSERVE · {len(reject)} REJECT \"\n f\"(of {len(drafts)} patterns scanned).\\n\\n---\\n\\n\"\n)\nbody = \"\".join(wt.render_draft_md(d) for d in (adopt + observe + reject))\nopen(out_path, \"w\").write(header + body)\nprint(f\"WORLD_SCAN_SUMMARY adopt={len(adopt)} observe={len(observe)} reject={len(reject)} total={len(drafts)}\")\nPYEOF\n\nif [ ! -s \"$OUTPUT_FILE\" ]; then\n log \"FATAL: translation produced no output file. Check ${ERR}.\"\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: translation failed. Check ${ERR}.\"\n exit 5\nfi\n\nSUMMARY=$(grep -h \"WORLD_SCAN_SUMMARY\" \"$LOG\" | tail -1 || echo \"summary unavailable\")\nlog \"step3 done: ${OUTPUT_FILE} ($(wc -l < \"$OUTPUT_FILE\") lines) — ${SUMMARY}\"\n\n# --- Step 4: notify (human reviews; never auto-merge) ---\ntelegram_alert \"🌐 world-scan ${WEEK_TAG} done. ${SUMMARY}. Draft probes staged at research/operations/_proposed/${WEEK_TAG}-world-scan-probes.md — review & promote ADOPT drafts by hand.\"\nlog \"DONE world-scan ${WEEK_TAG}\"\nexit 0\n"}, "c43b22330652a365d9fbe32ca1e5e8cdb03c8e23": {"t": 1785758294.8416717, "n": 8335, "h": "1d26bad6606b7ab9", "c": "#!/bin/bash\n# world-scan-run.sh — weekly external failure-pattern scan for the evolver.\n#\n# Reuse-first (2026-06-04): forked from ~/scripts/wr2-external-bench-run.sh.\n# ~80% reused (multi-LLM ingest+extract via a Claude agent, DeepSeek translate\n# via world_scan_translate.py, devils-advocate-style gate built into the\n# translator's deterministic grade, _proposed/ staging, Telegram). The only NEW\n# code is world_scan_translate.py (pattern -> draft executable probe).\n#\n# Pipeline:\n# 1. INGEST+EXTRACT (Claude Opus agent w/ web search): scan SRE/security/\n# agent-failure sources -> JSON list of failure patterns.\n# 2. TRANSLATE (world_scan_translate.py + DeepSeek): each pattern -> draft probe\n# with a DETERMINISTIC executability gate (ADOPT/OBSERVE/REJECT).\n# 3. STAGE: write drafts to research/operations/_proposed/-world-scan.md.\n# 4. NOTIFY: Telegram summary to Antonello. NEVER auto-merge; human promotes\n# an ADOPT draft into scar_probes.py by hand.\n#\n# Cron: weekly (1st-of-week guard inside). Schedule via LaunchAgent.\n# Cost: ~$0.05/week (Gemini/Claude OAuth + DeepSeek translate calls).\n\nset -euo pipefail\n\nLOGDIR=\"${HOME}/logs\"; mkdir -p \"$LOGDIR\"\nLOG=\"$LOGDIR/world-scan.log\"\nERR=\"$LOGDIR/world-scan.err.log\"\n\nHARNESS_DIR=\"${SCAR_REPLAY_DIR:-${HOME}/nuzantara-deploy/agent-library/scar_replay}\"\nREPO_ROOT=\"${WORLD_SCAN_REPO_ROOT:-${HOME}/nuzantara-deploy}\"\nWEEK_TAG=\"$(date +%Y-W%V)\"\nPROPOSED_DIR=\"${REPO_ROOT}/research/operations/_proposed\"\nOUTPUT_FILE=\"${PROPOSED_DIR}/${WEEK_TAG}-world-scan-probes.md\"\nPATTERNS_JSON=\"/tmp/world-scan-patterns-${WEEK_TAG}.json\"\n\nlog() { echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*\" >> \"$LOG\"; }\n\n# telegram_alert: reused verbatim from scar-replay-run.sh (#1090). Resolves token\n# + chat id from sanctioned vaults; tolerates OWNER vs APPROVAL chat-id naming\n# drift; suppresses silently if creds unresolved (Law 4 — never block on outage).\ntelegram_alert() {\n local msg=\"$1\"\n local tok=\"${TELEGRAM_BOT_TOKEN:-}\"\n local chat=\"${TELEGRAM_OWNER_CHAT_ID:-${TELEGRAM_APPROVAL_CHAT_ID:-}}\"\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [[ -f \"$f\" ]] || continue\n [[ -z \"${tok}\" ]] && tok=\"$(grep -m1 -E '^TELEGRAM_BOT_TOKEN=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n [[ -z \"${chat}\" ]] && chat=\"$(grep -m1 -E '^TELEGRAM_(OWNER|APPROVAL)_CHAT_ID=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n done\n fi\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n log \"WARN: telegram creds unresolved — human-alert suppressed: ${msg}\"\n return 0\n fi\n curl -sS --max-time 20 -X POST \"https://api.telegram.org/bot${tok}/sendMessage\" \\\n -d \"chat_id=${chat}\" -d \"text=${msg}\" >/dev/null 2>&1 || true\n}\n\nlog \"world-scan starting (week=${WEEK_TAG}, out=${OUTPUT_FILE})\"\n\n# --- idempotence: one scan per week ---\nif [ -s \"$OUTPUT_FILE\" ]; then\n log \"skip: ${OUTPUT_FILE} already exists ($(wc -l < \"$OUTPUT_FILE\") lines). Delete to re-run.\"\n exit 0\nfi\n\n# --- worktree-isolation guard (same discipline as scar-replay-run.sh): never\n# run from inside the shared deploy worktree ---\ncase \"$(pwd -P)/\" in\n \"${REPO_ROOT}/\"*) log \"REFUSE: cwd inside shared deploy worktree; aborting.\"; exit 0 ;;\nesac\n\n# --- secrets: DEEPSEEK_API_KEY (with vault drift fallback) + telegram ---\nDS_KEY=\"${DEEPSEEK_API_KEY:-}\"\nif [ -z \"$DS_KEY\" ]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [ -f \"$f\" ] || continue\n line=$(grep -m1 -E '^DEEPSEEK_API_KEY=' \"$f\" 2>/dev/null || true)\n [ -n \"$line\" ] && { DS_KEY=\"${line#DEEPSEEK_API_KEY=}\"; DS_KEY=\"${DS_KEY%\\\"}\"; DS_KEY=\"${DS_KEY#\\\"}\"; break; }\n done\nfi\nif [ -z \"$DS_KEY\" ]; then\n log \"FATAL: DEEPSEEK_API_KEY not found in any vault — cannot translate. Aborting.\"\n exit 2\nfi\nexport DEEPSEEK_API_KEY=\"$DS_KEY\"\n\nmkdir -p \"$PROPOSED_DIR\"\n\n# --- Step 1: INGEST + EXTRACT via Claude Opus agent (OAuth-only, web search) ---\n# Reuse of the wr2-external-bench invocation shape. The agent does the web\n# research and emits a strict JSON array of failure patterns to PATTERNS_JSON.\nINGEST_PROMPT=\"You are world-scan, the evolver's external research scout.\n\nResearch the LAST ~30 days of public best-practices and post-mortems on:\n - SRE / reliability engineering (toil, retries, idempotency, locking, queues)\n - chaos engineering & fault injection\n - autonomous-agent / LLM-agent failure modes (loops, drift, tool misuse, state)\n - CI/CD & git-worktree / deploy hazards\nUse web search. Prefer concrete engineering write-ups (incident reports, SRE\nbooks/blogs, postmortems), NOT listicles.\n\nExtract 6-12 DISTINCT failure patterns relevant to a self-improving ops agent\nthat runs local git worktrees, LaunchAgent cron, shell scripts, Postgres.\n\nWrite ONLY a strict JSON array to ${PATTERNS_JSON}, each item:\n {\\\"title\\\": \\\"...\\\", \\\"text\\\": \\\"2-4 sentence description of the failure mode and why it bites\\\", \\\"source\\\": \\\"url or outlet\\\"}\nNo prose around the JSON. Reject vague/cultural advice — only concrete, testable failure mechanics.\"\n\nCLAUDE_BIN=\"${HOME}/.local/bin/claude\"; [ -x \"$CLAUDE_BIN\" ] || CLAUDE_BIN=\"/opt/homebrew/bin/claude\"\n\nlog \"step1: ingest+extract via claude opus (web search)\"\ntimeout 1800 \"$CLAUDE_BIN\" -p \\\n --model claude-opus-4-8 \\\n --permission-mode bypassPermissions \\\n --max-budget-usd \"${WORLD_SCAN_MAX_BUDGET_USD:-5}\" \\\n \"$INGEST_PROMPT\" >> \"$LOG\" 2>> \"$ERR\" || log \"WARN: ingest agent exit=$?\"\n\nif [ ! -s \"$PATTERNS_JSON\" ]; then\n log \"FATAL: no patterns JSON produced at ${PATTERNS_JSON}. Aborting.\"\n # Telegram: this needs a human (ingest produced nothing).\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: ingest produced no patterns. Check ${ERR}.\"\n exit 3\nfi\nlog \"step1 done: $(wc -c < \"$PATTERNS_JSON\") bytes of patterns\"\n\n# --- Step 2+3: TRANSLATE each pattern + STAGE drafts ---\nlog \"step2: translate patterns -> draft probes (DeepSeek + deterministic gate)\"\nPYTHONPATH=\"${HARNESS_DIR}\" python3 - \"$PATTERNS_JSON\" \"$OUTPUT_FILE\" \"$WEEK_TAG\" <<'PYEOF' >> \"$LOG\" 2>> \"$ERR\"\nimport json, sys, os, datetime\nsys.path.insert(0, os.environ[\"PYTHONPATH\"])\nimport world_scan_translate as wt\n\npatterns_path, out_path, week = sys.argv[1], sys.argv[2], sys.argv[3]\nkey = os.environ[\"DEEPSEEK_API_KEY\"]\npatterns = json.load(open(patterns_path))\nif not isinstance(patterns, list):\n print(\"patterns JSON is not a list — abort\"); sys.exit(4)\n\ndrafts = []\nfor p in patterns:\n title = (p.get(\"title\") or \"untitled\").strip()\n text = (p.get(\"text\") or \"\") + \"\\nSource: \" + (p.get(\"source\") or \"\")\n d = wt.translate_pattern(key, title, text)\n d.source_refs = p.get(\"source\") or title\n drafts.append(d)\n\nadopt = [d for d in drafts if d.category == \"ADOPT\"]\nobserve = [d for d in drafts if d.category == \"OBSERVE\"]\nreject = [d for d in drafts if d.category == \"REJECT\"]\n\nheader = (\n f\"# World-Scan draft probes — {week}\\n\\n\"\n f\"> Auto-generated by world-scan (reuse-first fork of wr2-external-bench). \"\n f\"These are DRAFT replay-probes proposed from external failure patterns. \"\n f\"**Nothing here is live.** A human promotes an ADOPT draft into \"\n f\"`agent-library/scar_replay/scar_probes.py` by hand (fixture + assertion as \"\n f\"code) and commits it. Never auto-merged (Law 5).\\n\\n\"\n f\"**Summary:** {len(adopt)} ADOPT · {len(observe)} OBSERVE · {len(reject)} REJECT \"\n f\"(of {len(drafts)} patterns scanned).\\n\\n---\\n\\n\"\n)\nbody = \"\".join(wt.render_draft_md(d) for d in (adopt + observe + reject))\nopen(out_path, \"w\").write(header + body)\nprint(f\"WORLD_SCAN_SUMMARY adopt={len(adopt)} observe={len(observe)} reject={len(reject)} total={len(drafts)}\")\nPYEOF\n\nif [ ! -s \"$OUTPUT_FILE\" ]; then\n log \"FATAL: translation produced no output file. Check ${ERR}.\"\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: translation failed. Check ${ERR}.\"\n exit 5\nfi\n\nSUMMARY=$(grep -h \"WORLD_SCAN_SUMMARY\" \"$LOG\" | tail -1 || echo \"summary unavailable\")\nlog \"step3 done: ${OUTPUT_FILE} ($(wc -l < \"$OUTPUT_FILE\") lines) — ${SUMMARY}\"\n\n# --- Step 4: notify (human reviews; never auto-merge) ---\ntelegram_alert \"🌐 world-scan ${WEEK_TAG} done. ${SUMMARY}. Draft probes staged at research/operations/_proposed/${WEEK_TAG}-world-scan-probes.md — review & promote ADOPT drafts by hand.\"\nlog \"DONE world-scan ${WEEK_TAG}\"\nexit 0\n"}, "b005f859986dd37a17383d49a5bf3ac12f09c7e3": {"t": 1785758296.270696, "n": 8280, "h": "45bbfea04af649db", "c": "#!/bin/bash\n# world-scan-run.sh — weekly external failure-pattern scan for the evolver.\n#\n# Reuse-first (2026-06-04): forked from ~/scripts/wr2-external-bench-run.sh.\n# ~80% reused (multi-LLM ingest+extract via a Claude agent, DeepSeek translate\n# via world_scan_translate.py, devils-advocate-style gate built into the\n# translator's deterministic grade, _proposed/ staging, Telegram). The only NEW\n# code is world_scan_translate.py (pattern -> draft executable probe).\n#\n# Pipeline:\n# 1. INGEST+EXTRACT (Claude Opus agent w/ web search): scan SRE/security/\n# agent-failure sources -> JSON list of failure patterns.\n# 2. TRANSLATE (world_scan_translate.py + DeepSeek): each pattern -> draft probe\n# with a DETERMINISTIC executability gate (ADOPT/OBSERVE/REJECT).\n# 3. STAGE: write drafts to research/operations/_proposed/-world-scan.md.\n# 4. NOTIFY: Telegram summary to Antonello. NEVER auto-merge; human promotes\n# an ADOPT draft into scar_probes.py by hand.\n#\n# Cron: weekly (1st-of-week guard inside). Schedule via LaunchAgent.\n# Cost: ~$0.05/week (Gemini/Claude OAuth + DeepSeek translate calls).\n\nset -euo pipefail\n\nLOGDIR=\"${HOME}/logs\"; mkdir -p \"$LOGDIR\"\nLOG=\"$LOGDIR/world-scan.log\"\nERR=\"$LOGDIR/world-scan.err.log\"\n\nHARNESS_DIR=\"${SCAR_REPLAY_DIR:-${HOME}/nuzantara-deploy/agent-library/scar_replay}\"\nREPO_ROOT=\"${WORLD_SCAN_REPO_ROOT:-${HOME}/nuzantara-deploy}\"\nWEEK_TAG=\"$(date +%Y-W%V)\"\nPROPOSED_DIR=\"${REPO_ROOT}/research/operations/_proposed\"\nOUTPUT_FILE=\"${PROPOSED_DIR}/${WEEK_TAG}-world-scan-probes.md\"\nPATTERNS_JSON=\"/tmp/world-scan-patterns-${WEEK_TAG}.json\"\n\nlog() { echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*\" >> \"$LOG\"; }\n\n# telegram_alert: reused verbatim from scar-replay-run.sh (#1090). Resolves token\n# + chat id from sanctioned vaults; tolerates OWNER vs APPROVAL chat-id naming\n# drift; suppresses silently if creds unresolved (Law 4 — never block on outage).\ntelegram_alert() {\n local msg=\"$1\"\n local tok=\"${TELEGRAM_BOT_TOKEN:-}\"\n local chat=\"${TELEGRAM_OWNER_CHAT_ID:-${TELEGRAM_APPROVAL_CHAT_ID:-}}\"\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [[ -f \"$f\" ]] || continue\n [[ -z \"${tok}\" ]] && tok=\"$(grep -m1 -E '^TELEGRAM_BOT_TOKEN=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n [[ -z \"${chat}\" ]] && chat=\"$(grep -m1 -E '^TELEGRAM_(OWNER|APPROVAL)_CHAT_ID=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n done\n fi\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n log \"WARN: telegram creds unresolved — human-alert suppressed: ${msg}\"\n return 0\n fi\n curl -sS --max-time 20 -X POST \"https://api.telegram.org/bot${tok}/sendMessage\" \\\n -d \"chat_id=${chat}\" -d \"text=${msg}\" >/dev/null 2>&1 || true\n}\n\nlog \"world-scan starting (week=${WEEK_TAG}, out=${OUTPUT_FILE})\"\n\n# --- idempotence: one scan per week ---\nif [ -s \"$OUTPUT_FILE\" ]; then\n log \"skip: ${OUTPUT_FILE} already exists ($(wc -l < \"$OUTPUT_FILE\") lines). Delete to re-run.\"\n exit 0\nfi\n\n# --- worktree-isolation guard (same discipline as scar-replay-run.sh): never\n# run from inside the shared deploy worktree ---\ncase \"$(pwd -P)/\" in\n \"${REPO_ROOT}/\"*) log \"REFUSE: cwd inside shared deploy worktree; aborting.\"; exit 0 ;;\nesac\n\n# --- secrets: DEEPSEEK_API_KEY (with vault drift fallback) + telegram ---\nDS_KEY=\"${DEEPSEEK_API_KEY:-}\"\nif [ -z \"$DS_KEY\" ]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [ -f \"$f\" ] || continue\n line=$(grep -m1 -E '^DEEPSEEK_API_KEY=' \"$f\" 2>/dev/null || true)\n [ -n \"$line\" ] && { DS_KEY=\"${line#DEEPSEEK_API_KEY=}\"; DS_KEY=\"${DS_KEY%\\\"}\"; DS_KEY=\"${DS_KEY#\\\"}\"; break; }\n done\nfi\nif [ -z \"$DS_KEY\" ]; then\n log \"FATAL: DEEPSEEK_API_KEY not found in any vault — cannot translate. Aborting.\"\n exit 2\nfi\nexport DEEPSEEK_API_KEY=\"$DS_KEY\"\n\nmkdir -p \"$PROPOSED_DIR\"\n\n# --- Step 1: INGEST + EXTRACT via Claude Opus agent (OAuth-only, web search) ---\n# Reuse of the wr2-external-bench invocation shape. The agent does the web\n# research and emits a strict JSON array of failure patterns to PATTERNS_JSON.\nINGEST_PROMPT=\"You are world-scan, the evolver's external research scout.\n\nResearch the LAST ~30 days of public best-practices and post-mortems on:\n - SRE / reliability engineering (toil, retries, idempotency, locking, queues)\n - chaos engineering & fault injection\n - autonomous-agent / LLM-agent failure modes (loops, drift, tool misuse, state)\n - CI/CD & git-worktree / deploy hazards\nUse web search. Prefer concrete engineering write-ups (incident reports, SRE\nbooks/blogs, postmortems), NOT listicles.\n\nExtract 6-12 DISTINCT failure patterns relevant to a self-improving ops agent\nthat runs local git worktrees, LaunchAgent cron, shell scripts, Postgres.\n\nWrite ONLY a strict JSON array to ${PATTERNS_JSON}, each item:\n {\\\"title\\\": \\\"...\\\", \\\"text\\\": \\\"2-4 sentence description of the failure mode and why it bites\\\", \\\"source\\\": \\\"url or outlet\\\"}\nNo prose around the JSON. Reject vague/cultural advice — only concrete, testable failure mechanics.\"\n\nCLAUDE_BIN=\"${HOME}/.local/bin/claude\"; [ -x \"$CLAUDE_BIN\" ] || CLAUDE_BIN=\"/opt/homebrew/bin/claude\"\n\nlog \"step1: ingest+extract via claude opus (web search)\"\ntimeout 1800 \"$CLAUDE_BIN\" -p \\\n --model claude-opus-4-8 \\\n --permission-mode bypassPermissions \\\n \"$INGEST_PROMPT\" >> \"$LOG\" 2>> \"$ERR\" || log \"WARN: ingest agent exit=$?\"\n\nif [ ! -s \"$PATTERNS_JSON\" ]; then\n log \"FATAL: no patterns JSON produced at ${PATTERNS_JSON}. Aborting.\"\n # Telegram: this needs a human (ingest produced nothing).\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: ingest produced no patterns. Check ${ERR}.\"\n exit 3\nfi\nlog \"step1 done: $(wc -c < \"$PATTERNS_JSON\") bytes of patterns\"\n\n# --- Step 2+3: TRANSLATE each pattern + STAGE drafts ---\nlog \"step2: translate patterns -> draft probes (DeepSeek + deterministic gate)\"\nPYTHONPATH=\"${HARNESS_DIR}\" python3 - \"$PATTERNS_JSON\" \"$OUTPUT_FILE\" \"$WEEK_TAG\" <<'PYEOF' >> \"$LOG\" 2>> \"$ERR\"\nimport json, sys, os, datetime\nsys.path.insert(0, os.environ[\"PYTHONPATH\"])\nimport world_scan_translate as wt\n\npatterns_path, out_path, week = sys.argv[1], sys.argv[2], sys.argv[3]\nkey = os.environ[\"DEEPSEEK_API_KEY\"]\npatterns = json.load(open(patterns_path))\nif not isinstance(patterns, list):\n print(\"patterns JSON is not a list — abort\"); sys.exit(4)\n\ndrafts = []\nfor p in patterns:\n title = (p.get(\"title\") or \"untitled\").strip()\n text = (p.get(\"text\") or \"\") + \"\\nSource: \" + (p.get(\"source\") or \"\")\n d = wt.translate_pattern(key, title, text)\n d.source_refs = p.get(\"source\") or title\n drafts.append(d)\n\nadopt = [d for d in drafts if d.category == \"ADOPT\"]\nobserve = [d for d in drafts if d.category == \"OBSERVE\"]\nreject = [d for d in drafts if d.category == \"REJECT\"]\n\nheader = (\n f\"# World-Scan draft probes — {week}\\n\\n\"\n f\"> Auto-generated by world-scan (reuse-first fork of wr2-external-bench). \"\n f\"These are DRAFT replay-probes proposed from external failure patterns. \"\n f\"**Nothing here is live.** A human promotes an ADOPT draft into \"\n f\"`agent-library/scar_replay/scar_probes.py` by hand (fixture + assertion as \"\n f\"code) and commits it. Never auto-merged (Law 5).\\n\\n\"\n f\"**Summary:** {len(adopt)} ADOPT · {len(observe)} OBSERVE · {len(reject)} REJECT \"\n f\"(of {len(drafts)} patterns scanned).\\n\\n---\\n\\n\"\n)\nbody = \"\".join(wt.render_draft_md(d) for d in (adopt + observe + reject))\nopen(out_path, \"w\").write(header + body)\nprint(f\"WORLD_SCAN_SUMMARY adopt={len(adopt)} observe={len(observe)} reject={len(reject)} total={len(drafts)}\")\nPYEOF\n\nif [ ! -s \"$OUTPUT_FILE\" ]; then\n log \"FATAL: translation produced no output file. Check ${ERR}.\"\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: translation failed. Check ${ERR}.\"\n exit 5\nfi\n\nSUMMARY=$(grep -h \"WORLD_SCAN_SUMMARY\" \"$LOG\" | tail -1 || echo \"summary unavailable\")\nlog \"step3 done: ${OUTPUT_FILE} ($(wc -l < \"$OUTPUT_FILE\") lines) — ${SUMMARY}\"\n\n# --- Step 4: notify (human reviews; never auto-merge) ---\ntelegram_alert \"🌐 world-scan ${WEEK_TAG} done. ${SUMMARY}. Draft probes staged at research/operations/_proposed/${WEEK_TAG}-world-scan-probes.md — review & promote ADOPT drafts by hand.\"\nlog \"DONE world-scan ${WEEK_TAG}\"\nexit 0\n"}, "c6c3142a1f0bb3b195089705d9b3a88a5bce1896": {"t": 1785758297.456125, "n": 8296, "h": "066da63e4a87cabb", "c": "#!/bin/bash\n# world-scan-run.sh — weekly external failure-pattern scan for the evolver.\n#\n# Reuse-first (2026-06-04): forked from ~/scripts/wr2-external-bench-run.sh.\n# ~80% reused (multi-LLM ingest+extract via a Claude agent, DeepSeek translate\n# via world_scan_translate.py, devils-advocate-style gate built into the\n# translator's deterministic grade, _proposed/ staging, Telegram). The only NEW\n# code is world_scan_translate.py (pattern -> draft executable probe).\n#\n# Pipeline:\n# 1. INGEST+EXTRACT (Claude Opus agent w/ web search): scan SRE/security/\n# agent-failure sources -> JSON list of failure patterns.\n# 2. TRANSLATE (world_scan_translate.py + DeepSeek): each pattern -> draft probe\n# with a DETERMINISTIC executability gate (ADOPT/OBSERVE/REJECT).\n# 3. STAGE: write drafts to research/operations/_proposed/-world-scan.md.\n# 4. NOTIFY: Telegram summary to Antonello. NEVER auto-merge; human promotes\n# an ADOPT draft into scar_probes.py by hand.\n#\n# Cron: weekly (1st-of-week guard inside). Schedule via LaunchAgent.\n# Cost: ~$0.05/week (Gemini/Claude OAuth + DeepSeek translate calls).\n\nset -euo pipefail\n\nLOGDIR=\"${HOME}/logs\"; mkdir -p \"$LOGDIR\"\nLOG=\"$LOGDIR/world-scan.log\"\nERR=\"$LOGDIR/world-scan.err.log\"\n\nHARNESS_DIR=\"${SCAR_REPLAY_DIR:-${HOME}/Desktop/nuzantara-deploy/agent-library/scar_replay}\"\nREPO_ROOT=\"${WORLD_SCAN_REPO_ROOT:-${HOME}/Desktop/nuzantara-deploy}\"\nWEEK_TAG=\"$(date +%Y-W%V)\"\nPROPOSED_DIR=\"${REPO_ROOT}/research/operations/_proposed\"\nOUTPUT_FILE=\"${PROPOSED_DIR}/${WEEK_TAG}-world-scan-probes.md\"\nPATTERNS_JSON=\"/tmp/world-scan-patterns-${WEEK_TAG}.json\"\n\nlog() { echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*\" >> \"$LOG\"; }\n\n# telegram_alert: reused verbatim from scar-replay-run.sh (#1090). Resolves token\n# + chat id from sanctioned vaults; tolerates OWNER vs APPROVAL chat-id naming\n# drift; suppresses silently if creds unresolved (Law 4 — never block on outage).\ntelegram_alert() {\n local msg=\"$1\"\n local tok=\"${TELEGRAM_BOT_TOKEN:-}\"\n local chat=\"${TELEGRAM_OWNER_CHAT_ID:-${TELEGRAM_APPROVAL_CHAT_ID:-}}\"\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [[ -f \"$f\" ]] || continue\n [[ -z \"${tok}\" ]] && tok=\"$(grep -m1 -E '^TELEGRAM_BOT_TOKEN=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n [[ -z \"${chat}\" ]] && chat=\"$(grep -m1 -E '^TELEGRAM_(OWNER|APPROVAL)_CHAT_ID=' \"$f\" 2>/dev/null | cut -d= -f2- | tr -d '\"')\"\n done\n fi\n if [[ -z \"${tok}\" || -z \"${chat}\" ]]; then\n log \"WARN: telegram creds unresolved — human-alert suppressed: ${msg}\"\n return 0\n fi\n curl -sS --max-time 20 -X POST \"https://api.telegram.org/bot${tok}/sendMessage\" \\\n -d \"chat_id=${chat}\" -d \"text=${msg}\" >/dev/null 2>&1 || true\n}\n\nlog \"world-scan starting (week=${WEEK_TAG}, out=${OUTPUT_FILE})\"\n\n# --- idempotence: one scan per week ---\nif [ -s \"$OUTPUT_FILE\" ]; then\n log \"skip: ${OUTPUT_FILE} already exists ($(wc -l < \"$OUTPUT_FILE\") lines). Delete to re-run.\"\n exit 0\nfi\n\n# --- worktree-isolation guard (same discipline as scar-replay-run.sh): never\n# run from inside the shared deploy worktree ---\ncase \"$(pwd -P)/\" in\n \"${REPO_ROOT}/\"*) log \"REFUSE: cwd inside shared deploy worktree; aborting.\"; exit 0 ;;\nesac\n\n# --- secrets: DEEPSEEK_API_KEY (with vault drift fallback) + telegram ---\nDS_KEY=\"${DEEPSEEK_API_KEY:-}\"\nif [ -z \"$DS_KEY\" ]; then\n for f in \"${HOME}/.nuzantara-secrets.env\" \"${HOME}/.openclaw/workspace/.env.master\"; do\n [ -f \"$f\" ] || continue\n line=$(grep -m1 -E '^DEEPSEEK_API_KEY=' \"$f\" 2>/dev/null || true)\n [ -n \"$line\" ] && { DS_KEY=\"${line#DEEPSEEK_API_KEY=}\"; DS_KEY=\"${DS_KEY%\\\"}\"; DS_KEY=\"${DS_KEY#\\\"}\"; break; }\n done\nfi\nif [ -z \"$DS_KEY\" ]; then\n log \"FATAL: DEEPSEEK_API_KEY not found in any vault — cannot translate. Aborting.\"\n exit 2\nfi\nexport DEEPSEEK_API_KEY=\"$DS_KEY\"\n\nmkdir -p \"$PROPOSED_DIR\"\n\n# --- Step 1: INGEST + EXTRACT via Claude Opus agent (OAuth-only, web search) ---\n# Reuse of the wr2-external-bench invocation shape. The agent does the web\n# research and emits a strict JSON array of failure patterns to PATTERNS_JSON.\nINGEST_PROMPT=\"You are world-scan, the evolver's external research scout.\n\nResearch the LAST ~30 days of public best-practices and post-mortems on:\n - SRE / reliability engineering (toil, retries, idempotency, locking, queues)\n - chaos engineering & fault injection\n - autonomous-agent / LLM-agent failure modes (loops, drift, tool misuse, state)\n - CI/CD & git-worktree / deploy hazards\nUse web search. Prefer concrete engineering write-ups (incident reports, SRE\nbooks/blogs, postmortems), NOT listicles.\n\nExtract 6-12 DISTINCT failure patterns relevant to a self-improving ops agent\nthat runs local git worktrees, LaunchAgent cron, shell scripts, Postgres.\n\nWrite ONLY a strict JSON array to ${PATTERNS_JSON}, each item:\n {\\\"title\\\": \\\"...\\\", \\\"text\\\": \\\"2-4 sentence description of the failure mode and why it bites\\\", \\\"source\\\": \\\"url or outlet\\\"}\nNo prose around the JSON. Reject vague/cultural advice — only concrete, testable failure mechanics.\"\n\nCLAUDE_BIN=\"${HOME}/.local/bin/claude\"; [ -x \"$CLAUDE_BIN\" ] || CLAUDE_BIN=\"/opt/homebrew/bin/claude\"\n\nlog \"step1: ingest+extract via claude opus (web search)\"\ntimeout 1800 \"$CLAUDE_BIN\" -p \\\n --model claude-opus-4-8 \\\n --permission-mode bypassPermissions \\\n \"$INGEST_PROMPT\" >> \"$LOG\" 2>> \"$ERR\" || log \"WARN: ingest agent exit=$?\"\n\nif [ ! -s \"$PATTERNS_JSON\" ]; then\n log \"FATAL: no patterns JSON produced at ${PATTERNS_JSON}. Aborting.\"\n # Telegram: this needs a human (ingest produced nothing).\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: ingest produced no patterns. Check ${ERR}.\"\n exit 3\nfi\nlog \"step1 done: $(wc -c < \"$PATTERNS_JSON\") bytes of patterns\"\n\n# --- Step 2+3: TRANSLATE each pattern + STAGE drafts ---\nlog \"step2: translate patterns -> draft probes (DeepSeek + deterministic gate)\"\nPYTHONPATH=\"${HARNESS_DIR}\" python3 - \"$PATTERNS_JSON\" \"$OUTPUT_FILE\" \"$WEEK_TAG\" <<'PYEOF' >> \"$LOG\" 2>> \"$ERR\"\nimport json, sys, os, datetime\nsys.path.insert(0, os.environ[\"PYTHONPATH\"])\nimport world_scan_translate as wt\n\npatterns_path, out_path, week = sys.argv[1], sys.argv[2], sys.argv[3]\nkey = os.environ[\"DEEPSEEK_API_KEY\"]\npatterns = json.load(open(patterns_path))\nif not isinstance(patterns, list):\n print(\"patterns JSON is not a list — abort\"); sys.exit(4)\n\ndrafts = []\nfor p in patterns:\n title = (p.get(\"title\") or \"untitled\").strip()\n text = (p.get(\"text\") or \"\") + \"\\nSource: \" + (p.get(\"source\") or \"\")\n d = wt.translate_pattern(key, title, text)\n d.source_refs = p.get(\"source\") or title\n drafts.append(d)\n\nadopt = [d for d in drafts if d.category == \"ADOPT\"]\nobserve = [d for d in drafts if d.category == \"OBSERVE\"]\nreject = [d for d in drafts if d.category == \"REJECT\"]\n\nheader = (\n f\"# World-Scan draft probes — {week}\\n\\n\"\n f\"> Auto-generated by world-scan (reuse-first fork of wr2-external-bench). \"\n f\"These are DRAFT replay-probes proposed from external failure patterns. \"\n f\"**Nothing here is live.** A human promotes an ADOPT draft into \"\n f\"`agent-library/scar_replay/scar_probes.py` by hand (fixture + assertion as \"\n f\"code) and commits it. Never auto-merged (Law 5).\\n\\n\"\n f\"**Summary:** {len(adopt)} ADOPT · {len(observe)} OBSERVE · {len(reject)} REJECT \"\n f\"(of {len(drafts)} patterns scanned).\\n\\n---\\n\\n\"\n)\nbody = \"\".join(wt.render_draft_md(d) for d in (adopt + observe + reject))\nopen(out_path, \"w\").write(header + body)\nprint(f\"WORLD_SCAN_SUMMARY adopt={len(adopt)} observe={len(observe)} reject={len(reject)} total={len(drafts)}\")\nPYEOF\n\nif [ ! -s \"$OUTPUT_FILE\" ]; then\n log \"FATAL: translation produced no output file. Check ${ERR}.\"\n telegram_alert \"⚠️ world-scan ${WEEK_TAG}: translation failed. Check ${ERR}.\"\n exit 5\nfi\n\nSUMMARY=$(grep -h \"WORLD_SCAN_SUMMARY\" \"$LOG\" | tail -1 || echo \"summary unavailable\")\nlog \"step3 done: ${OUTPUT_FILE} ($(wc -l < \"$OUTPUT_FILE\") lines) — ${SUMMARY}\"\n\n# --- Step 4: notify (human reviews; never auto-merge) ---\ntelegram_alert \"🌐 world-scan ${WEEK_TAG} done. ${SUMMARY}. Draft probes staged at research/operations/_proposed/${WEEK_TAG}-world-scan-probes.md — review & promote ADOPT drafts by hand.\"\nlog \"DONE world-scan ${WEEK_TAG}\"\nexit 0\n"}}, "docs/specs/arsenal-probe-v1.md": {"9e8bb6055c42e72817fc7b01bc5035a2a7b7bf41": {"t": 1785746399.636789, "n": 8306, "h": "75d3df861bc8453a", "c": "# Arsenal Probe v1 — spec (DESIGN artifact, modus stage 2)\n\nDate: 2026-07-06 · Author: Fable 5 (interactive) · Implementer: Sonnet 5 (worktree ops-arsenal-probe)\nMandate: Zero 2026-07-06 \"sonda pesantemente\" — the quota-cascade can silently degrade to 2-deep\n(Codex 401 silent, agy keychain-bound, GLM 529/401, DeepSeek 402). Recommended since 2026-05-24,\nnever armed. This tool makes every AI seat's liveness EMPIRICAL, per-machine, per-context.\n\n## What it is\n\n`scripts/arsenal_probe.py` — a standalone, signal-only prober (never mutates anything outside\n`~/.organism/`). One run = live-probe every AI seat reachable from THIS machine, classify each\ninto an honest taxonomy, write a JSON report + heartbeat sidecar, detect transitions vs the\nprevious run. Consumed by: healer wrapper (Mini, 4h), proprioception (freshness + verdict reader),\nhumans (`--table`).\n\n## Seats & probe commands (each: subprocess, per-seat timeout, thread-parallel)\n\n| seat | probe | LIVE signal |\n|---|---|---|\n| claude | `$ARSENAL_CLAUDE_BIN -p \"Reply with exactly: PONG\" --model claude-sonnet-5` (default bin `/opt/homebrew/bin/claude`; strip `ANTHROPIC_API_KEY` from env, pass through `CLAUDE_CODE_OAUTH_TOKEN` if set) | `PONG` in stdout |\n| glm | token = `security find-generic-password -s glm-coding-plan-token -w` (NEVER logged); direct `curl` POST `https://api.z.ai/api/anthropic/v1/messages`, model `glm-5.2`, max_tokens 8, anthropic-version 2023-06-01 | HTTP 200 + `\"model\"` in body |\n| agy | `agy -p \"Reply with exactly: PONG\"` (which-resolve; also try `~/.local/bin/agy`) | `PONG` in stdout |\n| codex | `codex exec --sandbox read-only --skip-git-repo-check \"Reply with exactly: PONG\"` with stdin=DEVNULL (it blocks on open stdin) | `PONG` in stdout |\n| deepseek | key = parse `DEEPSEEK_API_KEY=` from `~/.openclaw/workspace/.env.master` (read in-python, value NEVER logged); `curl` POST `https://api.deepseek.com/chat/completions` model `deepseek-v4-flash`, max_tokens 1 | HTTP 200 |\n| ollama | `ollama list` → presence of `qwen3.5`; with `--live-gen` also 1-token `ollama run qwen3.5:9b` | model listed (or gen output) |\n| nlm | `nlm list notebooks` (which-resolve) | stdout parses as JSON (list or dict) |\n\nTimeouts (defaults, per-seat override via `--timeout SEC` global multiplier): claude 120s,\nglm 45s, agy 120s, codex 180s, deepseek 45s, ollama 30s (live-gen 120s), nlm 60s.\n\n## Status taxonomy (the heart — classify by OUTPUT CONTENT, never exit code alone; scar #2)\n\n- `LIVE` — the live signal observed.\n- `AUTH_DEAD` — output matches `401|Authentication Failed|token_revoked|refresh_token_reused|OAuth token|authentication failed` (codex/glm/claude/nlm auth class). For agy: only when NOT in an ssh context.\n- `CONTEXT_AUTH` — agy-style GUI-keychain failure while `SSH_CONNECTION`/`SSH_TTY` env present or no GUI session: the seat is dead IN THIS CONTEXT, possibly alive in GUI. Distinct because the cure differs (context, not credential).\n- `QUOTA_DEAD` — `out of extra usage|usage limit|quota|429|rate.limit|exhausted`.\n- `BALANCE_DEAD` — HTTP 402 / `Insufficient Balance` (deepseek class).\n- `MODEL_ERR` — `1211|Unknown Model` (glm class — config drift, e.g. the fable-5[1m] leak).\n- `SHED` — HTTP 529 / `overloaded` (provider-side transient load-shedding).\n- `TIMEOUT` — probe hit its per-seat timeout.\n- `CRED_UNAVAILABLE` — credential source absent/locked on this host (keychain locked → `security` exit 36/25300-class or empty in non-interactive; env.master missing; token file absent). NOT a seat death — a host limitation. Never strict-fails.\n- `NOT_INSTALLED` — binary not found on PATH (nor known fallback paths). Never strict-fails.\n- `UNKNOWN_ERR` — none of the above matched; evidence tail retained.\n\n`healthy` bool = status == LIVE. `context_limited` = status in {CONTEXT_AUTH, CRED_UNAVAILABLE, NOT_INSTALLED}.\nSTRICT-FAIL set (persistent + fixable): {AUTH_DEAD, BALANCE_DEAD, MODEL_ERR, UNKNOWN_ERR}.\n(QUOTA_DEAD/SHED/TIMEOUT are alarm-worthy transitions but transient — never exit-1.)\n\n## Machine awareness\n\n`machine_label()`: hostname → `m5` (Air-M5) / `pro` (Nuzantara) / `mini` (Mini-Pro2) / raw-lowercase.\nDefault seat selection = all 7; `--seats claude,glm,...` filters. REQUIRED map (used by `--strict`):\n`mini: [claude, glm, codex, ollama]` · `pro: [claude, codex, deepseek, ollama, nlm]` ·\n`m5: [claude, glm, agy, codex]` — a required seat in the STRICT-FAIL set → exit 1.\nNon-required seats always probed and reported (unless filtered), just never fail the run.\n\n## Outputs\n\n1. Report `~/.organism/arsenal/last.json` (atomic write via tempfile+rename; keep previous as\n `prev.json` before overwrite):\n```json\n{\"schema\": 1, \"machine\": \"mini\", \"ts\": \"2026-07-06T12:00:00Z\",\n \"context\": {\"ssh\": true, \"interactive\": false},\n \"seats\": [{\"seat\": \"glm\", \"status\": \"LIVE\", \"healthy\": true, \"latency_ms\": 1240,\n \"evidence\": \"HTTP 200 model glm-5.2\", \"required\": true}],\n \"transitions\": [{\"seat\": \"codex\", \"from\": \"LIVE\", \"to\": \"AUTH_DEAD\"}],\n \"summary\": {\"live\": 5, \"dead_strict\": 1, \"context_limited\": 1, \"transient\": 0}}\n```\n2. Heartbeat `~/.organism/last_seen/.arsenal_probe.json` — same shape as healer's:\n `{\"organ\": \".arsenal_probe\", \"status\": \"ok|degraded\", \"note\": \"\", \"ts\": ...}`\n (`degraded` iff any strict-fail among required seats).\n3. stdout: human table by default; `--json` full report; `--quiet` one summary line.\n\n## Flags\n\n`--seats CSV` · `--json` · `--table` (default) · `--quiet` · `--strict` · `--timeout MULT`\n(float multiplier on all per-seat timeouts) · `--live-gen` (ollama real generate) ·\n`--read-last` (NO probing: re-emit last.json as `{\"findings\": [seats not in ok-set]}` for the\nproprioception wrap consumer; missing file → `{\"findings\": [{\"seat\": \"(all)\", \"status\": \"NEVER_RAN\"}]}`) ·\n`--selftest` (see below).\n\n## Redaction (scar #4 — non-negotiable)\n\nEvidence tails (≤160 chars) pass through `scrub()`: replace `Bearer\\s+\\S+`, `sk-[A-Za-z0-9_-]{8,}`,\nany 24+ char alnum/`._-` token, and the literal values of any env var whose NAME matches\n`(TOKEN|KEY|PASSWORD|SECRET)` that the probe itself loaded, with ``. Credential values\nlive only in locals, never in the report, never in exceptions (wrap curl calls so the\nAuthorization header never appears in error strings). `security`/env.master reads must not echo.\n\n## Selftest (W84 blind-scan guard)\n\n`--selftest`: (a) classifier table — canned output samples per status (the real strings above:\nz.ai 1211 body, 529 body, codex token_revoked line, agy auth-failed line, deepseek 402, quota\nstrings) each classify correctly; (b) scrub() removes a planted fake token; (c) blind-scan guard:\na run that probed 0 seats must exit 2, never \"clean\"; (d) `--read-last` on a fixture file. Exit 0\nonly if all pass, print `SELFTEST OK — N checks`.\n\n## Tests — `scripts/tests/test_arsenal_probe.py` (pytest, NO live network/LLM calls)\n\nMonkeypatch subprocess/HTTP layers. Guilt AND innocence per classifier (e.g. `PONG` → LIVE never\nAUTH_DEAD; `1211` → MODEL_ERR never SHED; agy auth-fail + SSH_CONNECTION set → CONTEXT_AUTH,\nwithout ssh env → AUTH_DEAD). Transitions computed vs prev report. Strict exit semantics: required\nAUTH_DEAD → 1; CRED_UNAVAILABLE → 0. Redaction: fake `Bearer abc...` and a 40-char token never\nappear in report JSON. Atomic write leaves prev.json. `--read-last` fixtures (ok-set filtering,\nNEVER_RAN). Blind-scan exit 2. Aim ~20-30 focused tests. Style: mirror existing\n`scripts/tests/test_pending_arms_report.py` conventions (tmp_path, capsys).\n\n## Explicitly OUT of scope for the implementer (Fable does these after, funnel-in)\n\n- Edits to `scripts/proprioception.py` (guardian_freshness item + wrap registry entry)\n- Edits to `infra/healer/healer-run.sh` (receptor 4: run probe + transitions→ACTIONABLE + Telegram line)\n- `.github/workflows/immune-enforcement.yml` test wiring\n- `docs/runbooks/arsenal-probe.md`\n- PENDING-ARMS arming lines\n\n## Style contract\n\nPython 3.11 stdlib-only (subprocess, json, concurrent.futures, urllib.request for HTTP — no\nrequests dep), full type hints, logger-style stderr prints OK for a CLI tool, module docstring\nwith the one-line mission + scar references (#2 Esiste≠Armato, #4 secrets, W84 blind-scan).\nMatch the voice of `scripts/proprioception.py` (concise comments explaining WHY, not what).\n"}, "4e43a923b76601fcbae6810d61f0a6cf1fbc9bf5": {"t": 1785758296.2479012, "n": 8306, "h": "75d3df861bc8453a", "c": "# Arsenal Probe v1 — spec (DESIGN artifact, modus stage 2)\n\nDate: 2026-07-06 · Author: Fable 5 (interactive) · Implementer: Sonnet 5 (worktree ops-arsenal-probe)\nMandate: Zero 2026-07-06 \"sonda pesantemente\" — the quota-cascade can silently degrade to 2-deep\n(Codex 401 silent, agy keychain-bound, GLM 529/401, DeepSeek 402). Recommended since 2026-05-24,\nnever armed. This tool makes every AI seat's liveness EMPIRICAL, per-machine, per-context.\n\n## What it is\n\n`scripts/arsenal_probe.py` — a standalone, signal-only prober (never mutates anything outside\n`~/.organism/`). One run = live-probe every AI seat reachable from THIS machine, classify each\ninto an honest taxonomy, write a JSON report + heartbeat sidecar, detect transitions vs the\nprevious run. Consumed by: healer wrapper (Mini, 4h), proprioception (freshness + verdict reader),\nhumans (`--table`).\n\n## Seats & probe commands (each: subprocess, per-seat timeout, thread-parallel)\n\n| seat | probe | LIVE signal |\n|---|---|---|\n| claude | `$ARSENAL_CLAUDE_BIN -p \"Reply with exactly: PONG\" --model claude-sonnet-5` (default bin `/opt/homebrew/bin/claude`; strip `ANTHROPIC_API_KEY` from env, pass through `CLAUDE_CODE_OAUTH_TOKEN` if set) | `PONG` in stdout |\n| glm | token = `security find-generic-password -s glm-coding-plan-token -w` (NEVER logged); direct `curl` POST `https://api.z.ai/api/anthropic/v1/messages`, model `glm-5.2`, max_tokens 8, anthropic-version 2023-06-01 | HTTP 200 + `\"model\"` in body |\n| agy | `agy -p \"Reply with exactly: PONG\"` (which-resolve; also try `~/.local/bin/agy`) | `PONG` in stdout |\n| codex | `codex exec --sandbox read-only --skip-git-repo-check \"Reply with exactly: PONG\"` with stdin=DEVNULL (it blocks on open stdin) | `PONG` in stdout |\n| deepseek | key = parse `DEEPSEEK_API_KEY=` from `~/.openclaw/workspace/.env.master` (read in-python, value NEVER logged); `curl` POST `https://api.deepseek.com/chat/completions` model `deepseek-v4-flash`, max_tokens 1 | HTTP 200 |\n| ollama | `ollama list` → presence of `qwen3.5`; with `--live-gen` also 1-token `ollama run qwen3.5:9b` | model listed (or gen output) |\n| nlm | `nlm list notebooks` (which-resolve) | stdout parses as JSON (list or dict) |\n\nTimeouts (defaults, per-seat override via `--timeout SEC` global multiplier): claude 120s,\nglm 45s, agy 120s, codex 180s, deepseek 45s, ollama 30s (live-gen 120s), nlm 60s.\n\n## Status taxonomy (the heart — classify by OUTPUT CONTENT, never exit code alone; scar #2)\n\n- `LIVE` — the live signal observed.\n- `AUTH_DEAD` — output matches `401|Authentication Failed|token_revoked|refresh_token_reused|OAuth token|authentication failed` (codex/glm/claude/nlm auth class). For agy: only when NOT in an ssh context.\n- `CONTEXT_AUTH` — agy-style GUI-keychain failure while `SSH_CONNECTION`/`SSH_TTY` env present or no GUI session: the seat is dead IN THIS CONTEXT, possibly alive in GUI. Distinct because the cure differs (context, not credential).\n- `QUOTA_DEAD` — `out of extra usage|usage limit|quota|429|rate.limit|exhausted`.\n- `BALANCE_DEAD` — HTTP 402 / `Insufficient Balance` (deepseek class).\n- `MODEL_ERR` — `1211|Unknown Model` (glm class — config drift, e.g. the fable-5[1m] leak).\n- `SHED` — HTTP 529 / `overloaded` (provider-side transient load-shedding).\n- `TIMEOUT` — probe hit its per-seat timeout.\n- `CRED_UNAVAILABLE` — credential source absent/locked on this host (keychain locked → `security` exit 36/25300-class or empty in non-interactive; env.master missing; token file absent). NOT a seat death — a host limitation. Never strict-fails.\n- `NOT_INSTALLED` — binary not found on PATH (nor known fallback paths). Never strict-fails.\n- `UNKNOWN_ERR` — none of the above matched; evidence tail retained.\n\n`healthy` bool = status == LIVE. `context_limited` = status in {CONTEXT_AUTH, CRED_UNAVAILABLE, NOT_INSTALLED}.\nSTRICT-FAIL set (persistent + fixable): {AUTH_DEAD, BALANCE_DEAD, MODEL_ERR, UNKNOWN_ERR}.\n(QUOTA_DEAD/SHED/TIMEOUT are alarm-worthy transitions but transient — never exit-1.)\n\n## Machine awareness\n\n`machine_label()`: hostname → `m5` (Air-M5) / `pro` (Nuzantara) / `mini` (Mini-Pro2) / raw-lowercase.\nDefault seat selection = all 7; `--seats claude,glm,...` filters. REQUIRED map (used by `--strict`):\n`mini: [claude, glm, codex, ollama]` · `pro: [claude, codex, deepseek, ollama, nlm]` ·\n`m5: [claude, glm, agy, codex]` — a required seat in the STRICT-FAIL set → exit 1.\nNon-required seats always probed and reported (unless filtered), just never fail the run.\n\n## Outputs\n\n1. Report `~/.organism/arsenal/last.json` (atomic write via tempfile+rename; keep previous as\n `prev.json` before overwrite):\n```json\n{\"schema\": 1, \"machine\": \"mini\", \"ts\": \"2026-07-06T12:00:00Z\",\n \"context\": {\"ssh\": true, \"interactive\": false},\n \"seats\": [{\"seat\": \"glm\", \"status\": \"LIVE\", \"healthy\": true, \"latency_ms\": 1240,\n \"evidence\": \"HTTP 200 model glm-5.2\", \"required\": true}],\n \"transitions\": [{\"seat\": \"codex\", \"from\": \"LIVE\", \"to\": \"AUTH_DEAD\"}],\n \"summary\": {\"live\": 5, \"dead_strict\": 1, \"context_limited\": 1, \"transient\": 0}}\n```\n2. Heartbeat `~/.organism/last_seen/.arsenal_probe.json` — same shape as healer's:\n `{\"organ\": \".arsenal_probe\", \"status\": \"ok|degraded\", \"note\": \"\", \"ts\": ...}`\n (`degraded` iff any strict-fail among required seats).\n3. stdout: human table by default; `--json` full report; `--quiet` one summary line.\n\n## Flags\n\n`--seats CSV` · `--json` · `--table` (default) · `--quiet` · `--strict` · `--timeout MULT`\n(float multiplier on all per-seat timeouts) · `--live-gen` (ollama real generate) ·\n`--read-last` (NO probing: re-emit last.json as `{\"findings\": [seats not in ok-set]}` for the\nproprioception wrap consumer; missing file → `{\"findings\": [{\"seat\": \"(all)\", \"status\": \"NEVER_RAN\"}]}`) ·\n`--selftest` (see below).\n\n## Redaction (scar #4 — non-negotiable)\n\nEvidence tails (≤160 chars) pass through `scrub()`: replace `Bearer\\s+\\S+`, `sk-[A-Za-z0-9_-]{8,}`,\nany 24+ char alnum/`._-` token, and the literal values of any env var whose NAME matches\n`(TOKEN|KEY|PASSWORD|SECRET)` that the probe itself loaded, with ``. Credential values\nlive only in locals, never in the report, never in exceptions (wrap curl calls so the\nAuthorization header never appears in error strings). `security`/env.master reads must not echo.\n\n## Selftest (W84 blind-scan guard)\n\n`--selftest`: (a) classifier table — canned output samples per status (the real strings above:\nz.ai 1211 body, 529 body, codex token_revoked line, agy auth-failed line, deepseek 402, quota\nstrings) each classify correctly; (b) scrub() removes a planted fake token; (c) blind-scan guard:\na run that probed 0 seats must exit 2, never \"clean\"; (d) `--read-last` on a fixture file. Exit 0\nonly if all pass, print `SELFTEST OK — N checks`.\n\n## Tests — `scripts/tests/test_arsenal_probe.py` (pytest, NO live network/LLM calls)\n\nMonkeypatch subprocess/HTTP layers. Guilt AND innocence per classifier (e.g. `PONG` → LIVE never\nAUTH_DEAD; `1211` → MODEL_ERR never SHED; agy auth-fail + SSH_CONNECTION set → CONTEXT_AUTH,\nwithout ssh env → AUTH_DEAD). Transitions computed vs prev report. Strict exit semantics: required\nAUTH_DEAD → 1; CRED_UNAVAILABLE → 0. Redaction: fake `Bearer abc...` and a 40-char token never\nappear in report JSON. Atomic write leaves prev.json. `--read-last` fixtures (ok-set filtering,\nNEVER_RAN). Blind-scan exit 2. Aim ~20-30 focused tests. Style: mirror existing\n`scripts/tests/test_pending_arms_report.py` conventions (tmp_path, capsys).\n\n## Explicitly OUT of scope for the implementer (Fable does these after, funnel-in)\n\n- Edits to `scripts/proprioception.py` (guardian_freshness item + wrap registry entry)\n- Edits to `infra/healer/healer-run.sh` (receptor 4: run probe + transitions→ACTIONABLE + Telegram line)\n- `.github/workflows/immune-enforcement.yml` test wiring\n- `docs/runbooks/arsenal-probe.md`\n- PENDING-ARMS arming lines\n\n## Style contract\n\nPython 3.11 stdlib-only (subprocess, json, concurrent.futures, urllib.request for HTTP — no\nrequests dep), full type hints, logger-style stderr prints OK for a CLI tool, module docstring\nwith the one-line mission + scar references (#2 Esiste≠Armato, #4 secrets, W84 blind-scan).\nMatch the voice of `scripts/proprioception.py` (concise comments explaining WHY, not what).\n"}}, "docs/audits/2026-05-02-cell-openclaw-brainstorm/07_openclaw_deep_research.md": {"9e8bb6055c42e72817fc7b01bc5035a2a7b7bf41": {"t": 1785746582.731969, "n": 34193, "h": "c11e0bae09aa0645", "c": "# OpenClaw Deep Research: Architecture, Capabilities & Current Usage\n**Date**: 2026-05-02 | **Version**: openclaw 2026.3.31 | **Local Install**: `~/.openclaw/lib/node_modules/openclaw/` | **Config**: `~/.openclaw/openclaw.json`\n\n**Audience**: Claude (reader) + cross-LLM reviewers (Codex GPT-5.5, Gemini 3.1 Pro, DeepSeek V4 Reasoner) preparing to reason about OpenClaw's role in Nuzantara automations.\n\n---\n\n## Executive Summary\n\nOpenClaw is a **Node.js-based personal AI gateway** running a WebSocket control plane (`ws://127.0.0.1:18789`) that routes inbound messages from 23+ messaging channels (Telegram, WhatsApp, Discord, Slack, iMessage, etc.) to isolated agents, which dispatch LLM requests with multi-model fallback + tool streaming. The runtime is process-managed by LaunchAgent on macOS; the agent itself is embedded (RPC mode). \n\n**Nuzantara is using OpenClaw for**:\n- Primary messaging channel: Telegram (enabled, receiving message timeouts)\n- Multi-LLM routing: MiniMax M2.7 (primary) → Kimi K2.6 → DeepSeek Chat → Ollama Qwen3.5\n- Persistent memory: memory-core plugin (storing observations from tool use)\n- Orchestration: lobster plugin (workflow DSL, enabled)\n- Voice: voice-call skill (enabled)\n- Custom extensions: claude-mem (v12.1.0, marketplace install)\n\n**Version Gap**: Installed version is 2026.3.31 (released ~Mar 31); latest is 2026.4.29 (released Apr 30). Recent releases include Knowledge Agents system (12.1.0 in claude-mem), improved Telegram channel timeouts, and model failover hardening.\n\n---\n\n## A. Architecture\n\n### Runtime Model\n\nOpenClaw is a **Node.js daemon** (v22.22.0, bundled) running:\n- **Gateway** (port 18789, loopback-only, hybrid reload on config change)\n- **Control UI** (Web dashboard, http://127.0.0.1:18789)\n- **Pi agent** (embedded RPC, not external process)\n- **Channel adapters** (Telegram: grammY, Discord: discord.js, WhatsApp: Baileys, etc.)\n\n**Process Management**:\n- macOS: LaunchAgent (`~/Library/LaunchAgents/openclaw.plist` — managed by Nuzantara's `monitor-air.log` cron)\n- KeepAlive policy: checked via heartbeat monitor every 1h (Nuzantara config: `heartbeat.every=\"1h\"`)\n- Uptime target: 24/7 (threshold exceeded May 2, 2026 at 01:13 UTC — gap analysis in logs)\n\n### Agent Abstractions\n\n**Agent Definition** (`agents.list[]`):\n- Nuzantara has 2 agents:\n 1. **main**: primary, Telegram-bound, sandbox=off, model routing primary→fallback chain\n 2. **coder**: isolated workspace, sandbox=off, web tools denied (no web_search, web_fetch, browser)\n\n**Model Routing**:\n```\nmain:\n primary: openrouter/minimax/minimax-m2.7\n fallbacks: [kimi-k2.6, deepseek-chat, ollama/qwen3.5:9b]\n\ncoder:\n primary: openrouter/qwen/qwen3-max\n fallbacks: [qwen3.6-plus, kimi-k2.6, deepseek-reasoner, qwen3.5:9b]\n```\n\n**Fallback Chain Logic**:\n- Model request → try primary; if fails (auth, rate_limit, not_found) → try next fallback\n- Auth cooldown: 300s lockout after 10 auth failures in 60s window (gateway.auth.rateLimit)\n- Rate-limit cooldown: automatic provider cooldown (all-profiles-unavailable state) visible in logs (Mar 1-2, Google Gemini CLI exhausted)\n\n**Sandbox Modes**:\n- Default: `non-main` (separate container per agent workspace)\n- Nuzantara: `mode=off` for both agents (no isolation) + `prune.idleHours=24` (clean up idle containers)\n\n### Plugin System\n\nPlugins extend gateway capabilities via allow-list:\n\n**Loaded Plugins** (`plugins.entries`):\n- **memory-core** (enabled): observation feed + persistent storage\n- **memory-lancedb** (disabled): vector search backend (not active)\n- **lobster** (enabled): workflow orchestration DSL\n- **llm-task** (enabled): multi-step LLM orchestration\n- **voice-call** (enabled): phone/VOIP integration\n- **telegram** (implicit, channel adapter)\n\n**Plugin Trust Model**:\n- Plugins in `~/.openclaw/extensions/` are scanned; only those in `plugins.allow[]` are loaded\n- Nuzantara's installed plugin: `claude-mem` (v12.1.0) in `~/.openclaw/extensions/claude-mem/`\n- **Trust Warning**: claude-mem flagged in gateway logs as \"loaded without install/load-path provenance\" (implies manual fs install, not via package manager)\n\n### Skill System\n\nSkills add tools to agents via hooks + HTTP API.\n\n**Bundled Skills** (`~/.openclaw/lib/node_modules/openclaw/skills/`):\n- goplaces (Google Places API), xurl (URL shortener), voice-call (Twilio), notion, slack, discord, trello, spotify-player, etc.\n\n**Nuzantara Enabled Skills** (`skills.entries`):\n- **goplaces**: enabled (env: GOOGLE_PLACES_API_KEY)\n- **xurl**: enabled\n- **voice-call**: enabled\n- **notion**: enabled (env: NOTION_API_KEY)\n- **antigravity**: enabled\n\n**Custom Skills Directory**: `/Users/nuzantara/Desktop/nuzantara/apps/nuzantara-mcp/skills` (loaded via `skills.load.extraDirs[]`)\n\n### Channel Bindings\n\n**Telegram Channel** (enabled, dmPolicy=open):\n- **BotToken**: configured (redacted in config, present in plaintext)\n- **Allowed Senders**: `allowFrom=[\"*\"]` (open to all)\n- **Streaming**: disabled (responses sent as complete message blocks)\n- **Timeout**: 60s per message\n- **Retry**: 2 attempts, min 5s delay, max 60s delay, 0.5 jitter\n- **Known Issues**:\n - Network timeouts (ETIMEDOUT / EHOSTUNREACH observed Mar 1-2, 30s+ waits)\n - BOT_COMMANDS_TOO_MUCH (Telegram API limit: max 100 commands, Nuzantara registering 92-97, dropping 19-20 on each attempt)\n\n**Other Channels**:\n- WhatsApp, Discord, Slack, Signal, iMessage (BlueBubbles), IRC, Teams, Matrix: all disabled in config\n\n### Memory Model\n\n**memory-core** plugin:\n- SQLite database: `~/.openclaw/agents/main/agent/memory.db` (not visible in config, inferred from logs)\n- Observation feed: tool_use events → semantic summaries → injected into future sessions\n- Token-aware: context pruning mode=cache-ttl (1h TTL), compaction mode=safeguard (96k reserve floor, 40% history max)\n- Worker Service: runs on separate port (likely 37777 per claude-mem docs), managed by Bun\n- Vector backend: Chroma (if memory-lancedb enabled; currently off)\n\n### mcporter Integration\n\n**Tool Surface**:\n- Built-in: browser, canvas, nodes, cron, sessions\n- MCP tools: claude-mem (`search`, `timeline`, `get_observations`), custom skills\n\n**Safety Allowlist** (`tools.exec.safeBins[]`):\n```\nls, cat, tail, which, nuzantara-ops, mcporter\n```\n- Only these binaries can be executed without sandbox approval\n- `mcporter` is whitelisted (allows MCP tool invocation from agent)\n- **Known Issue**: mcporter allowlist audited Mar 22; safeBins entries not matching plugin config (audit log shows mismatch fixed via plugin reload)\n\n### Lobster Workflows\n\n**Lobster Plugin** (enabled):\n- DSL for multi-step orchestration\n- Workflow files: `~/.openclaw/workspace/.lobster/*.yml` (inferred)\n- Nuzantara logs show no active workflows, but plugin enabled for future use\n\n### Sandbox & Safety\n\n**Exec Approval Socket** (`exec-approvals.sock`):\n- Manual approval flow for unsafe commands\n- Not actively used in Nuzantara (sandbox=off, so no approvals needed)\n\n**Circuit Breaker** (`tools.loopDetection`):\n- Enabled globally (threshold=10 repeats)\n- Detectors:\n - **genericRepeat**: catch identical tool calls in sequence\n - **knownPollNoProgress**: detect polling without state change\n - **pingPong**: detect tool A → B → A cycles\n- Nuzantara: enabled, no circuit trips observed (logs clean on this metric)\n\n---\n\n## B. Current Capabilities\n\n### Agentic Tasks\n\n**Single-turn**: `openclaw agent --message \"query\"` (CLI or Gateway RPC)\n**Multi-turn**: Session state preserved in memory; model compaction + context pruning per config\n**Persistent Loops**: Supported via Lobster workflows (enabled but not in use)\n\n### Tool Use\n\n| Tool | Enabled | Notes |\n|------|---------|-------|\n| **web_search** | Yes | Integrated |\n| **web_fetch** | Yes | Integrated |\n| **browser** | No (coder agent denies) | Chrome control, snapshots, actions |\n| **exec** | Partial (safeBins only) | ls, cat, tail, nuzantara-ops, mcporter |\n| **file ops** | Via browser canvas | Not direct agent tool |\n| **image** | Yes (image model routing) | Primary: ollama/qwen2.5vl:7b, fallback: openrouter/qwen3-vl |\n| **canvas** (macOS) | Yes | A2UI protocol, push/reset/eval/snapshot |\n| **cron** | Yes | 24 jobs max (Nuzantara shows 0 active, scheduler may be frozen as of Apr 30) |\n| **custom MCP** | Yes (mcporter) | Route to local/remote MCP servers |\n\n**Multi-LLM Routing**: Each agent has primary + 3 fallback models; per-model params (temperature, max_tokens) configurable\n\n### Multi-LLM Routing\n\n**Provider Configuration**:\n- **openrouter**: native support, baseUrl=https://openrouter.ai/api/v1, 6 models configured\n- **deepseek**: native support, baseUrl=https://api.deepseek.com/v1, 2 models configured\n- **ollama**: local, baseUrl=http://127.0.0.1:11434, 0 models pre-configured (dynamic discovery)\n- **anthropic**: **NOT configured** (no ANTHROPIC_API_KEY in env; Nuzantara policy: banned)\n- **openai** (via openrouter): shim via openrouter provider\n\n**Per-Model Tuning**:\n```\ntemperature: 0.2–0.4 (reasoning), 0.3–0.4 (chat)\nmax_tokens: 4096–8192\nollama-specific: keep_alive=10m (memory cache), top_p=0.9, top_k=20\n```\n\n**Fallback Behavior**: \n- Try primary; if fails, cascade through fallbacks\n- Rate-limit cooldown (300s) applied per provider\n- Auth errors caught and retried with different auth profile (if multi-profile configured)\n\n### Persistent Memory\n\n**memory-core** (enabled):\n- **Lifecycle Hooks**: SessionStart → UserPromptSubmit → PostToolUse → Summary → SessionEnd\n- **Observation Compression**: tool_use events → semantic summaries (via Claude API or local LLM)\n- **Injection Strategy**: progressive disclosure (layer 1: index; layer 2: timeline; layer 3: full details)\n- **Search Tools**: `mem-search`, `timeline`, `get_observations` (MCP interface)\n- **Durability**: SQLite persistent store, survives session/process restarts\n\n### Channel I/O\n\n**Telegram** (primary):\n- Inbound: message events → matched to agent via binding (main agent, Telegram channel)\n- Outbound: agent reply → formatted as Telegram message → sent via botToken\n- **State**: connected (logs show recent message processing up to May 2 01:13)\n- **Timeouts**: retry logic (2 attempts, 5–60s backoff) masks network latency\n\n### Voice-Call\n\n**voice-call Skill** (enabled):\n- Integration: Twilio (inferred from OpenClaw docs; not explicitly in Nuzantara config)\n- Capabilities: accept voice calls, stream audio, TTS output (ElevenLabs or system fallback)\n- **Status in Nuzantara**: enabled but not actively tested\n\n### Browser Automation\n\n**Browser Tool** (available, not in use by main agent):\n- Chrome/Chromium control (dedicated OpenClaw instance)\n- Actions: snapshot, click, type, scroll, upload, profile switching\n- **Nuzantara**: coder agent has browser denied via `tools.deny=[\"browser\"]`\n\n### Workflow Orchestration (Lobster)\n\n**Lobster DSL** (enabled, not in active use):\n- YAML-based multi-step orchestration\n- Syntax: task dependencies, conditional routing, parallel execution\n- **Nuzantara**: loaded but no workflows observed in logs\n\n### Subagents\n\n**Subagent Pattern**: supported via agent routing (`bindings[]` match rules)\n- **Nuzantara**: 2 agents defined (main, coder); no inter-agent delegation observed\n- **Limitation**: agents are isolated; no direct parent-child RPC (agents are standalone)\n\n### Cron / Scheduled Jobs\n\n**Cron Tool**:\n- API: `POST /gateway/cron` or `openclaw cron add `\n- Max 24 jobs per gateway\n- **Nuzantara Status**: 0 active jobs logged (scheduler may be frozen since Apr 30 per audit notes)\n\n### Hooks\n\n**7 Lifecycle Hooks** (claude-mem):\n- SessionStart, UserPromptSubmit, PostToolUse, Summary, SessionEnd, PreToolUse, Stop\n- **Nuzantara Use**: memory-core hooks active (observation capture, summary generation)\n\n### Plugin Development\n\n**Plugin Template**:\n- Entry point: `plugin/index.ts` or `dist/index.js`\n- Hooks: export `hooks: { SessionStart, UserPromptSubmit, ... }`\n- MCP Tools: export `tools: [ ... ]` (JSON-RPC 2.0 interface)\n- **Nuzantara Custom Skills**: loaded from `/Users/nuzantara/Desktop/nuzantara/apps/nuzantara-mcp/skills/` (no plugins observed)\n\n### Embedded Agent Runtime\n\n**Pi Agent** (embedded, not delegated):\n- Runs in-process with gateway (RPC loopback)\n- Session state: maintained in gateway memory (not persistent across restarts without memory plugin)\n- Tool dispatch: streaming responses back to gateway → channel output\n\n---\n\n## C. What's NEW (Recent OpenClaw Releases)\n\n| Release | Date | Highlights |\n|---------|------|-----------|\n| **v2026.4.29** | Apr 30, 2026 | Stability improvements, auth profile migration docs |\n| **v2026.4.09** | Apr 9, 2026 | Knowledge Agents system (6 new MCP tools: build_corpus, prime_corpus, query_corpus, etc.) |\n| **v2026.3.31** | Mar 31, 2026 | **[INSTALLED]** DM pairing default, Telegram net timeout handling, provider enum changes |\n| **v2026.1.5** | Jan 5, 2026 | Image model config, agent.imageModel + fallbacks, model shorthands (opus, sonnet, gpt, gemini) |\n\n**Most Notable for Nuzantara**:\n- **Knowledge Agents** (v2026.4.09): Compile filtered corpus from claude-mem observations, query conversationally. 6 new MCP tools (build_corpus, list_corpora, prime_corpus, query_corpus, rebuild_corpus, reprime_corpus). **Not yet exploited.**\n- **Auth Profile Migration** (v2026.3.31 → v2026.4.29): DM pairing now default (requires approval codes); legacy \"open to all\" requires explicit dmPolicy=open + allowFrom=[\"*\"]. **Nuzantara already configured.**\n- **Telegram Timeout Hardening** (v2026.3.31): Retry + backoff for network errors (30s+ waits masked). **Experienced but handled gracefully.**\n\n**Claude-Mem Integration** (v12.1.0, installed via marketplace):\n- Knowledge agents now supported (native corpus build, prime, query MCP tools)\n- Smart-explore extended to 24 languages\n- File-read decision gate (PreToolUse hook blocks redundant reads using observation timeline)\n\n---\n\n## D. Comparison vs Alternatives\n\n| Dimension | OpenClaw | cron-agent-python (Nuzantara) | LangChain/LangGraph | Anthropic Agent SDK (direct) |\n|-----------|----------|------|-----------|---------|\n| **Primary UX** | Gateway + multi-channel | Python cron + custom CLI | Chain/graph DSL | Messages API |\n| **Multi-LLM** | Native (fallback chains) | Manual (explicit per-agent config) | LLMChain abstraction | No native support |\n| **Persistent Memory** | Plugin-based (memory-core) | NotebookLM (external) | No built-in | No built-in |\n| **Channel Binding** | 23+ integrations (Telegram, Discord, etc.) | CLI-only / webhooks | None (user's responsibility) | None |\n| **Workflow Orchestration** | Lobster DSL | Python task queue | LangGraph (DAG-based) | Claude Agent SDK (new) |\n| **Tool Streaming** | Yes (block streaming) | Manual | Yes (via tool classes) | Yes (native) |\n| **Sandbox** | Exec approval socket | None (direct subprocess) | None | None (external runner) |\n| **State Persistence** | SQLite (via plugins) | Disk-backed (JSON/state files) | Not built-in | Not built-in |\n| **Scaling** | Single gateway (local) | Multi-machine (cron dispatch) | App-level (doesn't scale infra) | Delegated to cloud provider |\n| **Ease of Setup** | `openclaw onboard` (90s) | Python venv + config | npm install + boilerplate | anthropic SDK (Python/JS) |\n\n**OpenClaw's Unique Value Propositions**:\n1. **Multi-channel inbox**: Single control plane for Telegram, WhatsApp, Discord, Slack, iMessage, IRC, Teams, Signal, etc.\n2. **Persistence out-of-the-box**: memory-core plugin captures observations + injects into future sessions (no manual logging)\n3. **Native fallback chains**: multi-model routing with per-provider cooldowns + auth management\n4. **Embedded + local**: runs on your machine (no cloud), binds to loopback only (no public expose by default)\n\n**Where OpenClaw Loses**:\n1. **No cloud sync**: single-machine deployment (no multi-region HA out of the box)\n2. **Provider enum rigidity**: only supports explicit providers (openrouter, deepseek, ollama, anthropic); no generic OpenAI-compatible override until v2026.3.31+ (baseUrl interpolation)\n3. **Command limit (Telegram)**: max 100 commands registered; Nuzantara hitting 92-97, dropping 19-20 on each sync\n4. **Scheduler frozen** (apr 30+): cron jobs not running (24-job queue inert); cause unknown\n\n**vs cron-agent-python** (Nuzantara parallel):\n- cron-agent-python: 19 active strategies, each runs independently on schedule; state decoupled (disk-backed JSON)\n- OpenClaw: single agent with multi-LLM routing; state unified in memory-core\n- **Recommendation**: cron-agent-python excels for **independent, scheduled tasks** (classification, analysis per-document); OpenClaw excels for **interactive, multi-turn conversations** with memory (Telegram chatbot + persistent context)\n\n---\n\n## E. Scaling Characteristics\n\n### Concurrency\n\n**Max Concurrent Agents**: 1 gateway, N agents (in Nuzantara: 2)\n- **Per-Agent Sessions**: Unbounded (session state pruned on demand)\n- **Concurrent Requests**: Limited by LLM provider rate limits (OpenRouter: ~100 req/min; DeepSeek: API doc unclear; Ollama: local, unbounded)\n- **Telegram Message Queue**: Sequential (one message processed at a time, 60s timeout → retry → backoff)\n\n### Memory Footprint\n\n| Component | RSS (Idle) | RSS (Active) | Notes |\n|-----------|-----------|-------------|-------|\n| Gateway process | ~200–300 MB | ~400–600 MB | Node.js runtime + channel adapters |\n| memory-core SQLite | ~10 MB | ~50+ MB | Depends on observation count + vector index |\n| Chroma (if enabled) | N/A | ~200+ MB | Python subprocess (uv-managed), not active in Nuzantara |\n| Total (Nuzantara) | ~250 MB | ~500+ MB | Measured via LaunchAgent memory monitor |\n\n### Latency Overhead\n\n| Operation | Latency | Notes |\n|-----------|---------|-------|\n| Gateway routing (inbound message) | <10ms | WebSocket demux + binding match |\n| Agent dispatch (to LLM) | <50ms | HTTP to OpenRouter/DeepSeek |\n| LLM request | 500ms–5s | Depends on model, fallback chain depth |\n| Response streaming (Telegram) | 1–30s | Tool execution + LLM generation + retry backoff |\n| Memory injection (PreToolUse) | 100–500ms | SQLite query + compression (if observation reuse) |\n\n**Gateway overhead is negligible** (<10% of E2E latency).\n\n### State Persistence\n\n**Durable Across Crashes**: Yes (if memory-core enabled)\n- Session state saved to SQLite after each tool_use hook\n- Observation timeline reconstructed on SessionStart\n\n**Graceful Shutdown**: LaunchAgent KeepAlive policy\n- monitored by `launchctl unload/load` (manual) or cron watchdog (Nuzantara)\n- Timeout: 30s (hard kill if not responsive)\n\n### Crash Recovery\n\n**KeepAlive=true** (Nuzantara config):\n- LaunchAgent auto-restarts gateway on exit (non-zero exit code)\n- State surviving: memory-core observations (durable), in-flight messages (lost, retried by Telegram)\n- **Observed**: gateway crashes not logged; LaunchAgent restarts appear transparent\n\n### Multi-Instance Topology\n\n**Federation**: Not supported natively\n- **Workaround**: run multiple gateways on different ports (18789, 18790, ...), but agents are isolated per gateway\n- **Nuzantara**: single gateway (port 18789); no multi-instance setup\n\n---\n\n## F. Security Model\n\n### Loopback-Only Binding\n\n**gateway.bind=loopback** (Nuzantara default):\n- Gateway listens on 127.0.0.1:18789 (localhost only)\n- No public internet exposure (requires SSH tunnel or Tailscale to access from remote)\n- **Threat Model**: protects against direct internet attacks; assumes local machine is secure\n\n### Auth Token & Rate Limiting\n\n**Token** (gateway.auth.token):\n- Long random string (example: 64 char base64)\n- Required in WebSocket `?token=...` query param or HTTP `Authorization: Bearer ` header\n- **Storage**: plaintext in `~/.openclaw/openclaw.json` (same permissions as SQLite DB)\n- **Rotation**: manual edit + `openclaw reload` (no auto-rotation tool visible)\n\n**Rate Limiting**:\n- **maxAttempts**: 10 failures in 60s window (Nuzantara config)\n- **lockoutMs**: 300s (5 min) lockout after threshold\n- **Scope**: per-IP (loopback is single IP, so affects all local clients equally)\n\n### exec-approvals.sock\n\n**Manual Approval Flow**:\n- Unsafe exec commands → `exec-approvals.sock` (Unix domain socket, `/tmp/exec-approvals-.sock`)\n- User approval via CLI: `echo \"approve \" | nc -U /tmp/exec-approvals-.sock`\n- **Nuzantara Status**: sandbox=off for both agents, so approval flow never triggered\n\n### Sandbox Modes\n\n| Mode | Isolation | Use Case |\n|------|-----------|----------|\n| **off** | None | Development, trusted local use |\n| **non-main** | Per-agent container | Multi-agent isolation (default agents.defaults.sandbox.mode) |\n| **full** | Per-session container | Maximum isolation (experimental) |\n\n**Nuzantara**: mode=off (no isolation). Rationale: single user, local machine, trusted workflows. Trade-off: agents can interfere (shared filesystem, process space).\n\n### Safety Bins Allowlist\n\n**Tools.exec.safeBins**:\n```\nls, cat, tail, which, nuzantara-ops, mcporter\n```\n- Only these binaries bypass approval flow\n- Others require exec approval (if sandbox=non-main or full)\n- **Known Issue** (Mar 22): safeBins not matching plugin config; resolved via plugin reload\n\n**Attack Surface**: agent can only run safe binaries; can't execute arbitrary commands (unless sandbox=off + agent has write access to filesystem, which it does in Nuzantara)\n\n### Plugin Trust Model\n\n**Plugin Loading** (`plugins.allow[]`):\n- Whitelist-based: only plugins in allow-list are loaded\n- Nuzantara loads: memory-core, lobster, llm-task, voice-call (implicit)\n- claude-mem: loaded from `~/.openclaw/extensions/claude-mem/` (manual install, not in core plugins.allow)\n\n**Trust Signals**:\n- Official plugins: signed releases, open-source GitHub\n- User plugins (Nuzantara custom skills): loaded from `/Desktop/nuzantara/apps/nuzantara-mcp/skills/` (same machine, implicit trust)\n- **Warning**: claude-mem flagged as \"loaded without install/load-path provenance\" → suggests side-load outside normal package path\n\n### Secret Handling\n\n**API Key Interpolation**:\n```json\n{\n \"providers\": {\n \"openrouter\": {\n \"apiKey\": \"${OPENROUTER_API_KEY}\"\n }\n }\n}\n```\n\n**Resolution**:\n1. Check environment variable (shellEnv=true in Nuzantara config, shell timeout 15s)\n2. Check EnvironmentVariables from LaunchAgent plist (if running as daemon)\n3. Fall back to plaintext in config (NOT recommended)\n\n**Nuzantara Config**:\n- OPENROUTER_API_KEY, DEEPSEEK_API_KEY, GOOGLE_PLACES_API_KEY, NOTION_API_KEY → in `~/.openclaw/.env` (not shown, but inferred from skills.env)\n- **Risk**: if `.env` checked into git, keys exposed\n\n---\n\n## G. Operational Model\n\n### LaunchAgent Management\n\n**Service File**: `~/Library/LaunchAgents/openclaw.plist` (macOS)\n- **Label**: com.openclaw.daemon\n- **Program**: node (bundled in ~/.openclaw/tools/node-v22.22.0/bin/node)\n- **KeepAlive**: true (auto-restart on exit)\n- **ThrottleInterval**: 30s (min time between restarts after crash)\n- **RunAtLoad**: true (start on login)\n\n**Manual Control**:\n```bash\nlaunchctl load ~/Library/LaunchAgents/openclaw.plist\nlaunchctl unload ~/Library/LaunchAgents/openclaw.plist\nlaunchctl start com.openclaw.daemon\nlaunchctl stop com.openclaw.daemon\n```\n\n**Nuzantara Monitoring**: cron job `monitor-air.log` (implied by logs; monitors for crashes + auto-restart failures)\n\n### Logs\n\n| Log | Path | Rotation | Notes |\n|-----|------|----------|-------|\n| **gateway.log** | `~/.openclaw/logs/gateway.log` | Yes (daily) | Main diagnostic output (diagnostic, channel, agent events) |\n| **gateway.err.log** | `~/.openclaw/logs/gateway.err.log` | Yes (daily) | Errors, warnings, stack traces |\n| **commands.log** | `~/.openclaw/logs/commands.log` | N/A | Slash command executions |\n| **config-audit.jsonl** | `~/.openclaw/logs/config-audit.jsonl` | Append | Config change audit trail |\n\n**Log Level**: `logging.level=info` (Nuzantara config); controlled via `openclaw config set logging.level=debug` (or restart with env var)\n\n**Retention**: no explicit TTL in config; logs grow unbounded (gateway.log: 21.7 GB as of May 2, gateway.err.log: 288 MB). **Risk**: disk space exhaustion.\n\n### Health Endpoint\n\n**Endpoint**: `GET /healthz` (Gateway)\n- **Response**: `{ \"status\": \"ok\" }` (200 OK) or 500 on error\n- **Nuzantara Use**: implied by monitor-air; likely polled every 5–60s\n\n### Metrics Export\n\n**Prometheus**: Not built-in to OpenClaw (as of v2026.3.31)\n- **Workaround**: parse logs with regex + ship to external metrics service\n- **Nuzantara**: no custom metrics exporter observed\n\n### Debugging\n\n**Verbose Mode**: `openclaw gateway --verbose` (CLI flag)\n**Log Level Override**: `OPENCLAW_LOG_LEVEL=debug` (env var at startup)\n**RPC Tracing**: gateway logs all RPC calls (agent → channel) with stack traces on failure\n\n**Trace an Agent Decision**:\n1. Enable debug logging\n2. Send message via Telegram\n3. Check gateway.log for SessionStart → UserPromptSubmit → tool_use → agent response flow\n4. Correlate with memory-core observations (check `.openclaw/agents/main/agent/memory.db` if needed)\n\n### Update Process\n\n**Manual Update**:\n```bash\nnpm install -g openclaw@latest\nopenclaw onboard --update # or --install-daemon to refresh daemon\n```\n\n**Safe Update (Nuzantara)**:\n1. `launchctl stop com.openclaw.daemon` (halt gateway)\n2. Backup `~/.openclaw/openclaw.json` + `~/.openclaw/workspace/`\n3. `npm install -g openclaw@latest`\n4. Review CHANGELOG for breaking changes\n5. Run `openclaw doctor` (auto-migrate config if needed)\n6. `launchctl start com.openclaw.daemon` (restart)\n\n**Auto-Update**: Not configurable in v2026.3.31; manual only.\n\n---\n\n## H. Known Issues & Pitfalls\n\n### 1. Provider Enum Rigidity\n\n**Issue**: openai-completions API wrapper only recognizes explicit `api: \"openai\"` (no generic override)\n\n**Impact**: Can't use arbitrary OpenAI-compatible backends (e.g., vLLM, LocalAI) without forking\n\n**Workaround** (Nuzantara): Use `api: \"openai-completions\"` with openrouter shim (all models exposed via openrouter baseURL)\n\n**Status**: Likely fixed in v2026.4.29 (baseUrl interpolation mentioned in changelog), but not tested against Nuzantara's installed v2026.3.31\n\n### 2. Secret Interpolation (`${VAR}` Only in env)\n\n**Issue**: `apiKey: \"${VAR}\"` resolves ONLY if VAR is in EnvironmentVariables (from LaunchAgent plist or shell env at startup), NOT from `.env` file or inline plaintext\n\n**Impact**: Easy to forget to export env var → silent fallback to missing key → auth failures\n\n**Example** (Nuzantara):\n```json\n{\n \"openrouter\": {\n \"apiKey\": \"${OPENROUTER_API_KEY}\" // resolves to env var if set, else null\n }\n}\n```\n\n**Workaround**: Explicitly set in LaunchAgent plist `EnvironmentVariables` section or `source ~/.openclaw/.env` before `launchctl load`\n\n### 3. mcporter Allowlist Quirks\n\n**Issue** (Mar 22 audit log): safeBins entries `ls, cat, tail, which, nuzantara-ops, mcporter` not matching plugin config → mcporter tool calls rejected\n\n**Root Cause**: Plugin loading race condition (safeBins checked before plugin registration completes)\n\n**Status**: Resolved in Nuzantara by manual reload (launchctl stop/start)\n\n**Fix Expected**: v2026.4.29+ (not tested)\n\n### 4. Plugin Trust Warnings\n\n**Issue**: claude-mem loaded from `~/.openclaw/extensions/claude-mem/` without install/load-path provenance\n\n**Impact**: Minor (code review recommended for untrusted sources); claude-mem is open-source + widely used\n\n### 5. Telegram Network Timeouts\n\n**Issue**: `getUpdates` request times out after 30s; retry backoff (5s → 60s) masks latency but creates gaps in message delivery (Apr 30 + May 2 logs show repeated timeouts)\n\n**Impact**: Inbound messages may be delayed 30–120s during network flaps\n\n**Cause**: Likely ISP or Telegram API throttling (Nuzantara in Bali, geographically distant from Telegram servers)\n\n**Workaround**: Increase timeout (Telegram: `timeoutSeconds=120`) or use webhook polling (if supported in next version)\n\n**Status**: Retry logic + backoff now in v2026.3.31; gracefully handled but not ideal UX\n\n### 6. BOT_COMMANDS_TOO_MUCH (Telegram API Limit)\n\n**Issue**: Telegram API limits /command menu to 100 entries; Nuzantara registering 92–97 commands (skills + custom), dropping 19–20 on each sync\n\n**Impact**: Some skills unavailable in Telegram /command autocomplete menu (but still callable via message mention)\n\n**Log Evidence**:\n```\n[telegram] rejected 92 commands (BOT_COMMANDS_TOO_MUCH); retrying with 73.\n[telegram] accepted 73 commands after BOT_COMMANDS_TOO_MUCH (started with 92; omitted 19).\n```\n\n**Root Cause**: Too many skills enabled (goplaces, xurl, voice-call, notion, antigravity) + OpenClaw bundled commands\n\n**Workaround**: Disable low-use skills in `skills.entries` (set enabled=false for unused ones)\n\n**Fix**: None in OpenClaw core (Telegram API limit). Requires operator intervention.\n\n### 7. Scheduler Frozen (Apr 30+)\n\n**Issue**: Cron jobs not running; 24-job queue inert\n\n**Evidence**: No cron logs in gateway.log since Apr 30; cron tool still responds to queries but doesn't execute\n\n**Impact**: Scheduled tasks (batch processing, daily summaries) missed\n\n**Likely Cause**: \n- Scheduler process crash (separate thread)\n- Job queue lock contention\n- State corruption after config reload\n\n**Status**: Unknown (no debugging done); requires `openclaw doctor` + manual job purge/recreate\n\n**Workaround**: Migrate to external cron runner (separate Python process with its own scheduler) or upgrade to v2026.4.29+\n\n### 8. Context Compaction False Positives\n\n**Issue**: context pruning + compaction may discard relevant observations if TTL expires before session end\n\n**Config** (Nuzantara):\n```\ncontextPruning.mode=cache-ttl, ttl=1h\ncompaction.mode=safeguard, reserveTokensFloor=96k\n```\n\n**Impact**: Multi-day sessions lose early context after 1h, even if still relevant\n\n**Workaround**: Increase TTL to 24h or use `mode: \"never\"` (disables pruning, risks context explosion)\n\n---\n\n## I. Roadmap & Future Direction\n\n**Public Roadmap**: https://github.com/openclaw/openclaw/issues (GitHub Issues, no official roadmap doc)\n\n**Recent PR Signals** (inferred from changelog):\n- **Knowledge Agents** (v2026.4.09): Building queryable \"brains\" from observation history (corpus build + prime + query)\n- **Auth Profile System** (v2026.3.31+): Multi-profile support + role-based failover (not fully enabled in Nuzantara)\n- **DM Pairing Security**: Default dmPolicy=pairing (require approval code for unknown senders) — security-first direction\n- **Provider Enum Expansion**: Support for more providers + generic OpenAI-compatible override (v2026.4.29 changelog hints)\n\n**Likely Future Work** (speculative):\n1. **Cloud Sync**: Multi-region HA + state replication (not in current roadmap, but enterprise feature request)\n2. **Structured Output**: Typed tool responses (Zod schema validation) — currently working, likely formalization\n3. **Voice Wake Improvements**: More language support, custom wake words (v2026.3.31 has voice-call, room for improvement)\n4. **Scheduler Stability**: Fix cron job queue race conditions (based on Apr 30 frozen state)\n5. **Knowledge Agent UI**: Web viewer for corpus browsing + semantic search (claude-mem v12.1.0 foundation)\n\n---\n\n## Summary Table: What Nuzantara Is Using vs. Available\n\n| Feature | Available | Enabled | Status |\n|---------|-----------|---------|--------|\n| **Multi-LLM Routing** | Yes (4 providers) | Yes (fallback chain) | Working, no issues |\n| **Persistent Memory** | Yes (memory-core) | Yes | Working, observations injected |\n| **Telegram Channel** | Yes | Yes | Working, but network timeouts every 30s+ |\n| **Workflow Orchestration** | Yes (Lobster) | Enabled but unused | Ready to use, no barriers |\n| **Knowledge Agents** | Yes (new in v12.1.0) | No | **NOT EXPLOITED** (v2026.4.09 feature) |\n| **Voice-Call Integration** | Yes | Yes | Enabled, not actively tested |\n| **Browser Automation** | Yes (main agent denied) | Partial (coder agent) | Available for coder agent |\n| **Cron Scheduler** | Yes (24 job limit) | Yes but frozen | **BROKEN** since Apr 30 |\n| **Custom Skills** | Yes (extraDirs) | Partially | `/nuzantara-mcp/skills/` not fully synced |\n| **Canvas (macOS)** | Yes | Implicit | Available if using macOS |\n| **Multi-Channel** | Yes (23 channels) | Only Telegram | Others disabled; can be enabled |\n\n---\n\n## Recommendations for Nuzantara\n\n1. **Upgrade to v2026.4.29** (from v2026.3.31): Knowledge Agents system ready; cron scheduler likely fixed; auth profiles stabilized\n2. **Exploit Knowledge Agents**: Build corpus from claude-mem observations; enable conversational history replay (query_corpus tool)\n3. **Fix Cron Scheduler**: Debug Apr 30 freeze; if unresolved in v2026.4.29, fallback to external cron-agent-python runner\n4. **Reduce Telegram Commands**: Disable unused skills (elite-longterm-memory, bluebubbles, discord, slack, spotify, trello) to stay under 100-command limit\n5. **Increase Telegram Timeout**: Raise `timeoutSeconds=120` to mask network latency (or implement webhook polling in next OpenClaw version)\n6. **Monitor Memory Growth**: Track `~/.openclaw/logs/gateway.log` size (currently 21.7 GB); implement log rotation or external log shipping\n7. **Test Voice-Call Skill**: Verify Twilio integration if voice interaction is planned\n8. **Sync Custom Skills**: Ensure `/nuzantara-mcp/skills/` fully registered with OpenClaw (check skills.entries for all custom entries)\n\n---\n\n## Files Referenced\n\n- **Config**: `/Users/nuzantara/.openclaw/openclaw.json` (v2026.3.31 schema)\n- **Installation**: `/Users/nuzantara/.openclaw/lib/node_modules/openclaw/`\n- **Logs**: `~/.openclaw/logs/gateway.log`, `gateway.err.log`\n- **Memory DB**: `~/.openclaw/agents/main/agent/memory.db` (SQLite, not visible in config)\n- **Workspace**: `~/.openclaw/workspace/` (markdown docs + agent state)\n- **Extensions**: `~/.openclaw/extensions/claude-mem/` (installed plugin)\n- **GitHub**: https://github.com/openclaw/openclaw (releases, issues, docs)\n- **Documentation**: https://docs.openclaw.ai (official, updated for v2026.4.29)\n- **claude-mem Marketplace**: `/Users/nuzantara/.claude/plugins/marketplaces/thedotmack/` (v12.1.0, AGPL-3.0)\n\n---\n\n**Document Compiled**: 2026-05-02 13:20 UTC | **Last Config Change**: 2026-05-02 13:20 UTC (Nuzantara-reported version)\n"}, "72ea7583cf1584a3b46956c063f0e71e069e04bb": {"t": 1785758295.7772791, "n": 34193, "h": "c11e0bae09aa0645", "c": "# OpenClaw Deep Research: Architecture, Capabilities & Current Usage\n**Date**: 2026-05-02 | **Version**: openclaw 2026.3.31 | **Local Install**: `~/.openclaw/lib/node_modules/openclaw/` | **Config**: `~/.openclaw/openclaw.json`\n\n**Audience**: Claude (reader) + cross-LLM reviewers (Codex GPT-5.5, Gemini 3.1 Pro, DeepSeek V4 Reasoner) preparing to reason about OpenClaw's role in Nuzantara automations.\n\n---\n\n## Executive Summary\n\nOpenClaw is a **Node.js-based personal AI gateway** running a WebSocket control plane (`ws://127.0.0.1:18789`) that routes inbound messages from 23+ messaging channels (Telegram, WhatsApp, Discord, Slack, iMessage, etc.) to isolated agents, which dispatch LLM requests with multi-model fallback + tool streaming. The runtime is process-managed by LaunchAgent on macOS; the agent itself is embedded (RPC mode). \n\n**Nuzantara is using OpenClaw for**:\n- Primary messaging channel: Telegram (enabled, receiving message timeouts)\n- Multi-LLM routing: MiniMax M2.7 (primary) → Kimi K2.6 → DeepSeek Chat → Ollama Qwen3.5\n- Persistent memory: memory-core plugin (storing observations from tool use)\n- Orchestration: lobster plugin (workflow DSL, enabled)\n- Voice: voice-call skill (enabled)\n- Custom extensions: claude-mem (v12.1.0, marketplace install)\n\n**Version Gap**: Installed version is 2026.3.31 (released ~Mar 31); latest is 2026.4.29 (released Apr 30). Recent releases include Knowledge Agents system (12.1.0 in claude-mem), improved Telegram channel timeouts, and model failover hardening.\n\n---\n\n## A. Architecture\n\n### Runtime Model\n\nOpenClaw is a **Node.js daemon** (v22.22.0, bundled) running:\n- **Gateway** (port 18789, loopback-only, hybrid reload on config change)\n- **Control UI** (Web dashboard, http://127.0.0.1:18789)\n- **Pi agent** (embedded RPC, not external process)\n- **Channel adapters** (Telegram: grammY, Discord: discord.js, WhatsApp: Baileys, etc.)\n\n**Process Management**:\n- macOS: LaunchAgent (`~/Library/LaunchAgents/openclaw.plist` — managed by Nuzantara's `monitor-air.log` cron)\n- KeepAlive policy: checked via heartbeat monitor every 1h (Nuzantara config: `heartbeat.every=\"1h\"`)\n- Uptime target: 24/7 (threshold exceeded May 2, 2026 at 01:13 UTC — gap analysis in logs)\n\n### Agent Abstractions\n\n**Agent Definition** (`agents.list[]`):\n- Nuzantara has 2 agents:\n 1. **main**: primary, Telegram-bound, sandbox=off, model routing primary→fallback chain\n 2. **coder**: isolated workspace, sandbox=off, web tools denied (no web_search, web_fetch, browser)\n\n**Model Routing**:\n```\nmain:\n primary: openrouter/minimax/minimax-m2.7\n fallbacks: [kimi-k2.6, deepseek-chat, ollama/qwen3.5:9b]\n\ncoder:\n primary: openrouter/qwen/qwen3-max\n fallbacks: [qwen3.6-plus, kimi-k2.6, deepseek-reasoner, qwen3.5:9b]\n```\n\n**Fallback Chain Logic**:\n- Model request → try primary; if fails (auth, rate_limit, not_found) → try next fallback\n- Auth cooldown: 300s lockout after 10 auth failures in 60s window (gateway.auth.rateLimit)\n- Rate-limit cooldown: automatic provider cooldown (all-profiles-unavailable state) visible in logs (Mar 1-2, Google Gemini CLI exhausted)\n\n**Sandbox Modes**:\n- Default: `non-main` (separate container per agent workspace)\n- Nuzantara: `mode=off` for both agents (no isolation) + `prune.idleHours=24` (clean up idle containers)\n\n### Plugin System\n\nPlugins extend gateway capabilities via allow-list:\n\n**Loaded Plugins** (`plugins.entries`):\n- **memory-core** (enabled): observation feed + persistent storage\n- **memory-lancedb** (disabled): vector search backend (not active)\n- **lobster** (enabled): workflow orchestration DSL\n- **llm-task** (enabled): multi-step LLM orchestration\n- **voice-call** (enabled): phone/VOIP integration\n- **telegram** (implicit, channel adapter)\n\n**Plugin Trust Model**:\n- Plugins in `~/.openclaw/extensions/` are scanned; only those in `plugins.allow[]` are loaded\n- Nuzantara's installed plugin: `claude-mem` (v12.1.0) in `~/.openclaw/extensions/claude-mem/`\n- **Trust Warning**: claude-mem flagged in gateway logs as \"loaded without install/load-path provenance\" (implies manual fs install, not via package manager)\n\n### Skill System\n\nSkills add tools to agents via hooks + HTTP API.\n\n**Bundled Skills** (`~/.openclaw/lib/node_modules/openclaw/skills/`):\n- goplaces (Google Places API), xurl (URL shortener), voice-call (Twilio), notion, slack, discord, trello, spotify-player, etc.\n\n**Nuzantara Enabled Skills** (`skills.entries`):\n- **goplaces**: enabled (env: GOOGLE_PLACES_API_KEY)\n- **xurl**: enabled\n- **voice-call**: enabled\n- **notion**: enabled (env: NOTION_API_KEY)\n- **antigravity**: enabled\n\n**Custom Skills Directory**: `/Users/nuzantara/Desktop/nuzantara/apps/nuzantara-mcp/skills` (loaded via `skills.load.extraDirs[]`)\n\n### Channel Bindings\n\n**Telegram Channel** (enabled, dmPolicy=open):\n- **BotToken**: configured (redacted in config, present in plaintext)\n- **Allowed Senders**: `allowFrom=[\"*\"]` (open to all)\n- **Streaming**: disabled (responses sent as complete message blocks)\n- **Timeout**: 60s per message\n- **Retry**: 2 attempts, min 5s delay, max 60s delay, 0.5 jitter\n- **Known Issues**:\n - Network timeouts (ETIMEDOUT / EHOSTUNREACH observed Mar 1-2, 30s+ waits)\n - BOT_COMMANDS_TOO_MUCH (Telegram API limit: max 100 commands, Nuzantara registering 92-97, dropping 19-20 on each attempt)\n\n**Other Channels**:\n- WhatsApp, Discord, Slack, Signal, iMessage (BlueBubbles), IRC, Teams, Matrix: all disabled in config\n\n### Memory Model\n\n**memory-core** plugin:\n- SQLite database: `~/.openclaw/agents/main/agent/memory.db` (not visible in config, inferred from logs)\n- Observation feed: tool_use events → semantic summaries → injected into future sessions\n- Token-aware: context pruning mode=cache-ttl (1h TTL), compaction mode=safeguard (96k reserve floor, 40% history max)\n- Worker Service: runs on separate port (likely 37777 per claude-mem docs), managed by Bun\n- Vector backend: Chroma (if memory-lancedb enabled; currently off)\n\n### mcporter Integration\n\n**Tool Surface**:\n- Built-in: browser, canvas, nodes, cron, sessions\n- MCP tools: claude-mem (`search`, `timeline`, `get_observations`), custom skills\n\n**Safety Allowlist** (`tools.exec.safeBins[]`):\n```\nls, cat, tail, which, nuzantara-ops, mcporter\n```\n- Only these binaries can be executed without sandbox approval\n- `mcporter` is whitelisted (allows MCP tool invocation from agent)\n- **Known Issue**: mcporter allowlist audited Mar 22; safeBins entries not matching plugin config (audit log shows mismatch fixed via plugin reload)\n\n### Lobster Workflows\n\n**Lobster Plugin** (enabled):\n- DSL for multi-step orchestration\n- Workflow files: `~/.openclaw/workspace/.lobster/*.yml` (inferred)\n- Nuzantara logs show no active workflows, but plugin enabled for future use\n\n### Sandbox & Safety\n\n**Exec Approval Socket** (`exec-approvals.sock`):\n- Manual approval flow for unsafe commands\n- Not actively used in Nuzantara (sandbox=off, so no approvals needed)\n\n**Circuit Breaker** (`tools.loopDetection`):\n- Enabled globally (threshold=10 repeats)\n- Detectors:\n - **genericRepeat**: catch identical tool calls in sequence\n - **knownPollNoProgress**: detect polling without state change\n - **pingPong**: detect tool A → B → A cycles\n- Nuzantara: enabled, no circuit trips observed (logs clean on this metric)\n\n---\n\n## B. Current Capabilities\n\n### Agentic Tasks\n\n**Single-turn**: `openclaw agent --message \"query\"` (CLI or Gateway RPC)\n**Multi-turn**: Session state preserved in memory; model compaction + context pruning per config\n**Persistent Loops**: Supported via Lobster workflows (enabled but not in use)\n\n### Tool Use\n\n| Tool | Enabled | Notes |\n|------|---------|-------|\n| **web_search** | Yes | Integrated |\n| **web_fetch** | Yes | Integrated |\n| **browser** | No (coder agent denies) | Chrome control, snapshots, actions |\n| **exec** | Partial (safeBins only) | ls, cat, tail, nuzantara-ops, mcporter |\n| **file ops** | Via browser canvas | Not direct agent tool |\n| **image** | Yes (image model routing) | Primary: ollama/qwen2.5vl:7b, fallback: openrouter/qwen3-vl |\n| **canvas** (macOS) | Yes | A2UI protocol, push/reset/eval/snapshot |\n| **cron** | Yes | 24 jobs max (Nuzantara shows 0 active, scheduler may be frozen as of Apr 30) |\n| **custom MCP** | Yes (mcporter) | Route to local/remote MCP servers |\n\n**Multi-LLM Routing**: Each agent has primary + 3 fallback models; per-model params (temperature, max_tokens) configurable\n\n### Multi-LLM Routing\n\n**Provider Configuration**:\n- **openrouter**: native support, baseUrl=https://openrouter.ai/api/v1, 6 models configured\n- **deepseek**: native support, baseUrl=https://api.deepseek.com/v1, 2 models configured\n- **ollama**: local, baseUrl=http://127.0.0.1:11434, 0 models pre-configured (dynamic discovery)\n- **anthropic**: **NOT configured** (no ANTHROPIC_API_KEY in env; Nuzantara policy: banned)\n- **openai** (via openrouter): shim via openrouter provider\n\n**Per-Model Tuning**:\n```\ntemperature: 0.2–0.4 (reasoning), 0.3–0.4 (chat)\nmax_tokens: 4096–8192\nollama-specific: keep_alive=10m (memory cache), top_p=0.9, top_k=20\n```\n\n**Fallback Behavior**: \n- Try primary; if fails, cascade through fallbacks\n- Rate-limit cooldown (300s) applied per provider\n- Auth errors caught and retried with different auth profile (if multi-profile configured)\n\n### Persistent Memory\n\n**memory-core** (enabled):\n- **Lifecycle Hooks**: SessionStart → UserPromptSubmit → PostToolUse → Summary → SessionEnd\n- **Observation Compression**: tool_use events → semantic summaries (via Claude API or local LLM)\n- **Injection Strategy**: progressive disclosure (layer 1: index; layer 2: timeline; layer 3: full details)\n- **Search Tools**: `mem-search`, `timeline`, `get_observations` (MCP interface)\n- **Durability**: SQLite persistent store, survives session/process restarts\n\n### Channel I/O\n\n**Telegram** (primary):\n- Inbound: message events → matched to agent via binding (main agent, Telegram channel)\n- Outbound: agent reply → formatted as Telegram message → sent via botToken\n- **State**: connected (logs show recent message processing up to May 2 01:13)\n- **Timeouts**: retry logic (2 attempts, 5–60s backoff) masks network latency\n\n### Voice-Call\n\n**voice-call Skill** (enabled):\n- Integration: Twilio (inferred from OpenClaw docs; not explicitly in Nuzantara config)\n- Capabilities: accept voice calls, stream audio, TTS output (ElevenLabs or system fallback)\n- **Status in Nuzantara**: enabled but not actively tested\n\n### Browser Automation\n\n**Browser Tool** (available, not in use by main agent):\n- Chrome/Chromium control (dedicated OpenClaw instance)\n- Actions: snapshot, click, type, scroll, upload, profile switching\n- **Nuzantara**: coder agent has browser denied via `tools.deny=[\"browser\"]`\n\n### Workflow Orchestration (Lobster)\n\n**Lobster DSL** (enabled, not in active use):\n- YAML-based multi-step orchestration\n- Syntax: task dependencies, conditional routing, parallel execution\n- **Nuzantara**: loaded but no workflows observed in logs\n\n### Subagents\n\n**Subagent Pattern**: supported via agent routing (`bindings[]` match rules)\n- **Nuzantara**: 2 agents defined (main, coder); no inter-agent delegation observed\n- **Limitation**: agents are isolated; no direct parent-child RPC (agents are standalone)\n\n### Cron / Scheduled Jobs\n\n**Cron Tool**:\n- API: `POST /gateway/cron` or `openclaw cron add `\n- Max 24 jobs per gateway\n- **Nuzantara Status**: 0 active jobs logged (scheduler may be frozen since Apr 30 per audit notes)\n\n### Hooks\n\n**7 Lifecycle Hooks** (claude-mem):\n- SessionStart, UserPromptSubmit, PostToolUse, Summary, SessionEnd, PreToolUse, Stop\n- **Nuzantara Use**: memory-core hooks active (observation capture, summary generation)\n\n### Plugin Development\n\n**Plugin Template**:\n- Entry point: `plugin/index.ts` or `dist/index.js`\n- Hooks: export `hooks: { SessionStart, UserPromptSubmit, ... }`\n- MCP Tools: export `tools: [ ... ]` (JSON-RPC 2.0 interface)\n- **Nuzantara Custom Skills**: loaded from `/Users/nuzantara/Desktop/nuzantara/apps/nuzantara-mcp/skills/` (no plugins observed)\n\n### Embedded Agent Runtime\n\n**Pi Agent** (embedded, not delegated):\n- Runs in-process with gateway (RPC loopback)\n- Session state: maintained in gateway memory (not persistent across restarts without memory plugin)\n- Tool dispatch: streaming responses back to gateway → channel output\n\n---\n\n## C. What's NEW (Recent OpenClaw Releases)\n\n| Release | Date | Highlights |\n|---------|------|-----------|\n| **v2026.4.29** | Apr 30, 2026 | Stability improvements, auth profile migration docs |\n| **v2026.4.09** | Apr 9, 2026 | Knowledge Agents system (6 new MCP tools: build_corpus, prime_corpus, query_corpus, etc.) |\n| **v2026.3.31** | Mar 31, 2026 | **[INSTALLED]** DM pairing default, Telegram net timeout handling, provider enum changes |\n| **v2026.1.5** | Jan 5, 2026 | Image model config, agent.imageModel + fallbacks, model shorthands (opus, sonnet, gpt, gemini) |\n\n**Most Notable for Nuzantara**:\n- **Knowledge Agents** (v2026.4.09): Compile filtered corpus from claude-mem observations, query conversationally. 6 new MCP tools (build_corpus, list_corpora, prime_corpus, query_corpus, rebuild_corpus, reprime_corpus). **Not yet exploited.**\n- **Auth Profile Migration** (v2026.3.31 → v2026.4.29): DM pairing now default (requires approval codes); legacy \"open to all\" requires explicit dmPolicy=open + allowFrom=[\"*\"]. **Nuzantara already configured.**\n- **Telegram Timeout Hardening** (v2026.3.31): Retry + backoff for network errors (30s+ waits masked). **Experienced but handled gracefully.**\n\n**Claude-Mem Integration** (v12.1.0, installed via marketplace):\n- Knowledge agents now supported (native corpus build, prime, query MCP tools)\n- Smart-explore extended to 24 languages\n- File-read decision gate (PreToolUse hook blocks redundant reads using observation timeline)\n\n---\n\n## D. Comparison vs Alternatives\n\n| Dimension | OpenClaw | cron-agent-python (Nuzantara) | LangChain/LangGraph | Anthropic Agent SDK (direct) |\n|-----------|----------|------|-----------|---------|\n| **Primary UX** | Gateway + multi-channel | Python cron + custom CLI | Chain/graph DSL | Messages API |\n| **Multi-LLM** | Native (fallback chains) | Manual (explicit per-agent config) | LLMChain abstraction | No native support |\n| **Persistent Memory** | Plugin-based (memory-core) | NotebookLM (external) | No built-in | No built-in |\n| **Channel Binding** | 23+ integrations (Telegram, Discord, etc.) | CLI-only / webhooks | None (user's responsibility) | None |\n| **Workflow Orchestration** | Lobster DSL | Python task queue | LangGraph (DAG-based) | Claude Agent SDK (new) |\n| **Tool Streaming** | Yes (block streaming) | Manual | Yes (via tool classes) | Yes (native) |\n| **Sandbox** | Exec approval socket | None (direct subprocess) | None | None (external runner) |\n| **State Persistence** | SQLite (via plugins) | Disk-backed (JSON/state files) | Not built-in | Not built-in |\n| **Scaling** | Single gateway (local) | Multi-machine (cron dispatch) | App-level (doesn't scale infra) | Delegated to cloud provider |\n| **Ease of Setup** | `openclaw onboard` (90s) | Python venv + config | npm install + boilerplate | anthropic SDK (Python/JS) |\n\n**OpenClaw's Unique Value Propositions**:\n1. **Multi-channel inbox**: Single control plane for Telegram, WhatsApp, Discord, Slack, iMessage, IRC, Teams, Signal, etc.\n2. **Persistence out-of-the-box**: memory-core plugin captures observations + injects into future sessions (no manual logging)\n3. **Native fallback chains**: multi-model routing with per-provider cooldowns + auth management\n4. **Embedded + local**: runs on your machine (no cloud), binds to loopback only (no public expose by default)\n\n**Where OpenClaw Loses**:\n1. **No cloud sync**: single-machine deployment (no multi-region HA out of the box)\n2. **Provider enum rigidity**: only supports explicit providers (openrouter, deepseek, ollama, anthropic); no generic OpenAI-compatible override until v2026.3.31+ (baseUrl interpolation)\n3. **Command limit (Telegram)**: max 100 commands registered; Nuzantara hitting 92-97, dropping 19-20 on each sync\n4. **Scheduler frozen** (apr 30+): cron jobs not running (24-job queue inert); cause unknown\n\n**vs cron-agent-python** (Nuzantara parallel):\n- cron-agent-python: 19 active strategies, each runs independently on schedule; state decoupled (disk-backed JSON)\n- OpenClaw: single agent with multi-LLM routing; state unified in memory-core\n- **Recommendation**: cron-agent-python excels for **independent, scheduled tasks** (classification, analysis per-document); OpenClaw excels for **interactive, multi-turn conversations** with memory (Telegram chatbot + persistent context)\n\n---\n\n## E. Scaling Characteristics\n\n### Concurrency\n\n**Max Concurrent Agents**: 1 gateway, N agents (in Nuzantara: 2)\n- **Per-Agent Sessions**: Unbounded (session state pruned on demand)\n- **Concurrent Requests**: Limited by LLM provider rate limits (OpenRouter: ~100 req/min; DeepSeek: API doc unclear; Ollama: local, unbounded)\n- **Telegram Message Queue**: Sequential (one message processed at a time, 60s timeout → retry → backoff)\n\n### Memory Footprint\n\n| Component | RSS (Idle) | RSS (Active) | Notes |\n|-----------|-----------|-------------|-------|\n| Gateway process | ~200–300 MB | ~400–600 MB | Node.js runtime + channel adapters |\n| memory-core SQLite | ~10 MB | ~50+ MB | Depends on observation count + vector index |\n| Chroma (if enabled) | N/A | ~200+ MB | Python subprocess (uv-managed), not active in Nuzantara |\n| Total (Nuzantara) | ~250 MB | ~500+ MB | Measured via LaunchAgent memory monitor |\n\n### Latency Overhead\n\n| Operation | Latency | Notes |\n|-----------|---------|-------|\n| Gateway routing (inbound message) | <10ms | WebSocket demux + binding match |\n| Agent dispatch (to LLM) | <50ms | HTTP to OpenRouter/DeepSeek |\n| LLM request | 500ms–5s | Depends on model, fallback chain depth |\n| Response streaming (Telegram) | 1–30s | Tool execution + LLM generation + retry backoff |\n| Memory injection (PreToolUse) | 100–500ms | SQLite query + compression (if observation reuse) |\n\n**Gateway overhead is negligible** (<10% of E2E latency).\n\n### State Persistence\n\n**Durable Across Crashes**: Yes (if memory-core enabled)\n- Session state saved to SQLite after each tool_use hook\n- Observation timeline reconstructed on SessionStart\n\n**Graceful Shutdown**: LaunchAgent KeepAlive policy\n- monitored by `launchctl unload/load` (manual) or cron watchdog (Nuzantara)\n- Timeout: 30s (hard kill if not responsive)\n\n### Crash Recovery\n\n**KeepAlive=true** (Nuzantara config):\n- LaunchAgent auto-restarts gateway on exit (non-zero exit code)\n- State surviving: memory-core observations (durable), in-flight messages (lost, retried by Telegram)\n- **Observed**: gateway crashes not logged; LaunchAgent restarts appear transparent\n\n### Multi-Instance Topology\n\n**Federation**: Not supported natively\n- **Workaround**: run multiple gateways on different ports (18789, 18790, ...), but agents are isolated per gateway\n- **Nuzantara**: single gateway (port 18789); no multi-instance setup\n\n---\n\n## F. Security Model\n\n### Loopback-Only Binding\n\n**gateway.bind=loopback** (Nuzantara default):\n- Gateway listens on 127.0.0.1:18789 (localhost only)\n- No public internet exposure (requires SSH tunnel or Tailscale to access from remote)\n- **Threat Model**: protects against direct internet attacks; assumes local machine is secure\n\n### Auth Token & Rate Limiting\n\n**Token** (gateway.auth.token):\n- Long random string (example: 64 char base64)\n- Required in WebSocket `?token=...` query param or HTTP `Authorization: Bearer ` header\n- **Storage**: plaintext in `~/.openclaw/openclaw.json` (same permissions as SQLite DB)\n- **Rotation**: manual edit + `openclaw reload` (no auto-rotation tool visible)\n\n**Rate Limiting**:\n- **maxAttempts**: 10 failures in 60s window (Nuzantara config)\n- **lockoutMs**: 300s (5 min) lockout after threshold\n- **Scope**: per-IP (loopback is single IP, so affects all local clients equally)\n\n### exec-approvals.sock\n\n**Manual Approval Flow**:\n- Unsafe exec commands → `exec-approvals.sock` (Unix domain socket, `/tmp/exec-approvals-.sock`)\n- User approval via CLI: `echo \"approve \" | nc -U /tmp/exec-approvals-.sock`\n- **Nuzantara Status**: sandbox=off for both agents, so approval flow never triggered\n\n### Sandbox Modes\n\n| Mode | Isolation | Use Case |\n|------|-----------|----------|\n| **off** | None | Development, trusted local use |\n| **non-main** | Per-agent container | Multi-agent isolation (default agents.defaults.sandbox.mode) |\n| **full** | Per-session container | Maximum isolation (experimental) |\n\n**Nuzantara**: mode=off (no isolation). Rationale: single user, local machine, trusted workflows. Trade-off: agents can interfere (shared filesystem, process space).\n\n### Safety Bins Allowlist\n\n**Tools.exec.safeBins**:\n```\nls, cat, tail, which, nuzantara-ops, mcporter\n```\n- Only these binaries bypass approval flow\n- Others require exec approval (if sandbox=non-main or full)\n- **Known Issue** (Mar 22): safeBins not matching plugin config; resolved via plugin reload\n\n**Attack Surface**: agent can only run safe binaries; can't execute arbitrary commands (unless sandbox=off + agent has write access to filesystem, which it does in Nuzantara)\n\n### Plugin Trust Model\n\n**Plugin Loading** (`plugins.allow[]`):\n- Whitelist-based: only plugins in allow-list are loaded\n- Nuzantara loads: memory-core, lobster, llm-task, voice-call (implicit)\n- claude-mem: loaded from `~/.openclaw/extensions/claude-mem/` (manual install, not in core plugins.allow)\n\n**Trust Signals**:\n- Official plugins: signed releases, open-source GitHub\n- User plugins (Nuzantara custom skills): loaded from `/Desktop/nuzantara/apps/nuzantara-mcp/skills/` (same machine, implicit trust)\n- **Warning**: claude-mem flagged as \"loaded without install/load-path provenance\" → suggests side-load outside normal package path\n\n### Secret Handling\n\n**API Key Interpolation**:\n```json\n{\n \"providers\": {\n \"openrouter\": {\n \"apiKey\": \"${OPENROUTER_API_KEY}\"\n }\n }\n}\n```\n\n**Resolution**:\n1. Check environment variable (shellEnv=true in Nuzantara config, shell timeout 15s)\n2. Check EnvironmentVariables from LaunchAgent plist (if running as daemon)\n3. Fall back to plaintext in config (NOT recommended)\n\n**Nuzantara Config**:\n- OPENROUTER_API_KEY, DEEPSEEK_API_KEY, GOOGLE_PLACES_API_KEY, NOTION_API_KEY → in `~/.openclaw/.env` (not shown, but inferred from skills.env)\n- **Risk**: if `.env` checked into git, keys exposed\n\n---\n\n## G. Operational Model\n\n### LaunchAgent Management\n\n**Service File**: `~/Library/LaunchAgents/openclaw.plist` (macOS)\n- **Label**: com.openclaw.daemon\n- **Program**: node (bundled in ~/.openclaw/tools/node-v22.22.0/bin/node)\n- **KeepAlive**: true (auto-restart on exit)\n- **ThrottleInterval**: 30s (min time between restarts after crash)\n- **RunAtLoad**: true (start on login)\n\n**Manual Control**:\n```bash\nlaunchctl load ~/Library/LaunchAgents/openclaw.plist\nlaunchctl unload ~/Library/LaunchAgents/openclaw.plist\nlaunchctl start com.openclaw.daemon\nlaunchctl stop com.openclaw.daemon\n```\n\n**Nuzantara Monitoring**: cron job `monitor-air.log` (implied by logs; monitors for crashes + auto-restart failures)\n\n### Logs\n\n| Log | Path | Rotation | Notes |\n|-----|------|----------|-------|\n| **gateway.log** | `~/.openclaw/logs/gateway.log` | Yes (daily) | Main diagnostic output (diagnostic, channel, agent events) |\n| **gateway.err.log** | `~/.openclaw/logs/gateway.err.log` | Yes (daily) | Errors, warnings, stack traces |\n| **commands.log** | `~/.openclaw/logs/commands.log` | N/A | Slash command executions |\n| **config-audit.jsonl** | `~/.openclaw/logs/config-audit.jsonl` | Append | Config change audit trail |\n\n**Log Level**: `logging.level=info` (Nuzantara config); controlled via `openclaw config set logging.level=debug` (or restart with env var)\n\n**Retention**: no explicit TTL in config; logs grow unbounded (gateway.log: 21.7 GB as of May 2, gateway.err.log: 288 MB). **Risk**: disk space exhaustion.\n\n### Health Endpoint\n\n**Endpoint**: `GET /healthz` (Gateway)\n- **Response**: `{ \"status\": \"ok\" }` (200 OK) or 500 on error\n- **Nuzantara Use**: implied by monitor-air; likely polled every 5–60s\n\n### Metrics Export\n\n**Prometheus**: Not built-in to OpenClaw (as of v2026.3.31)\n- **Workaround**: parse logs with regex + ship to external metrics service\n- **Nuzantara**: no custom metrics exporter observed\n\n### Debugging\n\n**Verbose Mode**: `openclaw gateway --verbose` (CLI flag)\n**Log Level Override**: `OPENCLAW_LOG_LEVEL=debug` (env var at startup)\n**RPC Tracing**: gateway logs all RPC calls (agent → channel) with stack traces on failure\n\n**Trace an Agent Decision**:\n1. Enable debug logging\n2. Send message via Telegram\n3. Check gateway.log for SessionStart → UserPromptSubmit → tool_use → agent response flow\n4. Correlate with memory-core observations (check `.openclaw/agents/main/agent/memory.db` if needed)\n\n### Update Process\n\n**Manual Update**:\n```bash\nnpm install -g openclaw@latest\nopenclaw onboard --update # or --install-daemon to refresh daemon\n```\n\n**Safe Update (Nuzantara)**:\n1. `launchctl stop com.openclaw.daemon` (halt gateway)\n2. Backup `~/.openclaw/openclaw.json` + `~/.openclaw/workspace/`\n3. `npm install -g openclaw@latest`\n4. Review CHANGELOG for breaking changes\n5. Run `openclaw doctor` (auto-migrate config if needed)\n6. `launchctl start com.openclaw.daemon` (restart)\n\n**Auto-Update**: Not configurable in v2026.3.31; manual only.\n\n---\n\n## H. Known Issues & Pitfalls\n\n### 1. Provider Enum Rigidity\n\n**Issue**: openai-completions API wrapper only recognizes explicit `api: \"openai\"` (no generic override)\n\n**Impact**: Can't use arbitrary OpenAI-compatible backends (e.g., vLLM, LocalAI) without forking\n\n**Workaround** (Nuzantara): Use `api: \"openai-completions\"` with openrouter shim (all models exposed via openrouter baseURL)\n\n**Status**: Likely fixed in v2026.4.29 (baseUrl interpolation mentioned in changelog), but not tested against Nuzantara's installed v2026.3.31\n\n### 2. Secret Interpolation (`${VAR}` Only in env)\n\n**Issue**: `apiKey: \"${VAR}\"` resolves ONLY if VAR is in EnvironmentVariables (from LaunchAgent plist or shell env at startup), NOT from `.env` file or inline plaintext\n\n**Impact**: Easy to forget to export env var → silent fallback to missing key → auth failures\n\n**Example** (Nuzantara):\n```json\n{\n \"openrouter\": {\n \"apiKey\": \"${OPENROUTER_API_KEY}\" // resolves to env var if set, else null\n }\n}\n```\n\n**Workaround**: Explicitly set in LaunchAgent plist `EnvironmentVariables` section or `source ~/.openclaw/.env` before `launchctl load`\n\n### 3. mcporter Allowlist Quirks\n\n**Issue** (Mar 22 audit log): safeBins entries `ls, cat, tail, which, nuzantara-ops, mcporter` not matching plugin config → mcporter tool calls rejected\n\n**Root Cause**: Plugin loading race condition (safeBins checked before plugin registration completes)\n\n**Status**: Resolved in Nuzantara by manual reload (launchctl stop/start)\n\n**Fix Expected**: v2026.4.29+ (not tested)\n\n### 4. Plugin Trust Warnings\n\n**Issue**: claude-mem loaded from `~/.openclaw/extensions/claude-mem/` without install/load-path provenance\n\n**Impact**: Minor (code review recommended for untrusted sources); claude-mem is open-source + widely used\n\n### 5. Telegram Network Timeouts\n\n**Issue**: `getUpdates` request times out after 30s; retry backoff (5s → 60s) masks latency but creates gaps in message delivery (Apr 30 + May 2 logs show repeated timeouts)\n\n**Impact**: Inbound messages may be delayed 30–120s during network flaps\n\n**Cause**: Likely ISP or Telegram API throttling (Nuzantara in Bali, geographically distant from Telegram servers)\n\n**Workaround**: Increase timeout (Telegram: `timeoutSeconds=120`) or use webhook polling (if supported in next version)\n\n**Status**: Retry logic + backoff now in v2026.3.31; gracefully handled but not ideal UX\n\n### 6. BOT_COMMANDS_TOO_MUCH (Telegram API Limit)\n\n**Issue**: Telegram API limits /command menu to 100 entries; Nuzantara registering 92–97 commands (skills + custom), dropping 19–20 on each sync\n\n**Impact**: Some skills unavailable in Telegram /command autocomplete menu (but still callable via message mention)\n\n**Log Evidence**:\n```\n[telegram] rejected 92 commands (BOT_COMMANDS_TOO_MUCH); retrying with 73.\n[telegram] accepted 73 commands after BOT_COMMANDS_TOO_MUCH (started with 92; omitted 19).\n```\n\n**Root Cause**: Too many skills enabled (goplaces, xurl, voice-call, notion, antigravity) + OpenClaw bundled commands\n\n**Workaround**: Disable low-use skills in `skills.entries` (set enabled=false for unused ones)\n\n**Fix**: None in OpenClaw core (Telegram API limit). Requires operator intervention.\n\n### 7. Scheduler Frozen (Apr 30+)\n\n**Issue**: Cron jobs not running; 24-job queue inert\n\n**Evidence**: No cron logs in gateway.log since Apr 30; cron tool still responds to queries but doesn't execute\n\n**Impact**: Scheduled tasks (batch processing, daily summaries) missed\n\n**Likely Cause**: \n- Scheduler process crash (separate thread)\n- Job queue lock contention\n- State corruption after config reload\n\n**Status**: Unknown (no debugging done); requires `openclaw doctor` + manual job purge/recreate\n\n**Workaround**: Migrate to external cron runner (separate Python process with its own scheduler) or upgrade to v2026.4.29+\n\n### 8. Context Compaction False Positives\n\n**Issue**: context pruning + compaction may discard relevant observations if TTL expires before session end\n\n**Config** (Nuzantara):\n```\ncontextPruning.mode=cache-ttl, ttl=1h\ncompaction.mode=safeguard, reserveTokensFloor=96k\n```\n\n**Impact**: Multi-day sessions lose early context after 1h, even if still relevant\n\n**Workaround**: Increase TTL to 24h or use `mode: \"never\"` (disables pruning, risks context explosion)\n\n---\n\n## I. Roadmap & Future Direction\n\n**Public Roadmap**: https://github.com/openclaw/openclaw/issues (GitHub Issues, no official roadmap doc)\n\n**Recent PR Signals** (inferred from changelog):\n- **Knowledge Agents** (v2026.4.09): Building queryable \"brains\" from observation history (corpus build + prime + query)\n- **Auth Profile System** (v2026.3.31+): Multi-profile support + role-based failover (not fully enabled in Nuzantara)\n- **DM Pairing Security**: Default dmPolicy=pairing (require approval code for unknown senders) — security-first direction\n- **Provider Enum Expansion**: Support for more providers + generic OpenAI-compatible override (v2026.4.29 changelog hints)\n\n**Likely Future Work** (speculative):\n1. **Cloud Sync**: Multi-region HA + state replication (not in current roadmap, but enterprise feature request)\n2. **Structured Output**: Typed tool responses (Zod schema validation) — currently working, likely formalization\n3. **Voice Wake Improvements**: More language support, custom wake words (v2026.3.31 has voice-call, room for improvement)\n4. **Scheduler Stability**: Fix cron job queue race conditions (based on Apr 30 frozen state)\n5. **Knowledge Agent UI**: Web viewer for corpus browsing + semantic search (claude-mem v12.1.0 foundation)\n\n---\n\n## Summary Table: What Nuzantara Is Using vs. Available\n\n| Feature | Available | Enabled | Status |\n|---------|-----------|---------|--------|\n| **Multi-LLM Routing** | Yes (4 providers) | Yes (fallback chain) | Working, no issues |\n| **Persistent Memory** | Yes (memory-core) | Yes | Working, observations injected |\n| **Telegram Channel** | Yes | Yes | Working, but network timeouts every 30s+ |\n| **Workflow Orchestration** | Yes (Lobster) | Enabled but unused | Ready to use, no barriers |\n| **Knowledge Agents** | Yes (new in v12.1.0) | No | **NOT EXPLOITED** (v2026.4.09 feature) |\n| **Voice-Call Integration** | Yes | Yes | Enabled, not actively tested |\n| **Browser Automation** | Yes (main agent denied) | Partial (coder agent) | Available for coder agent |\n| **Cron Scheduler** | Yes (24 job limit) | Yes but frozen | **BROKEN** since Apr 30 |\n| **Custom Skills** | Yes (extraDirs) | Partially | `/nuzantara-mcp/skills/` not fully synced |\n| **Canvas (macOS)** | Yes | Implicit | Available if using macOS |\n| **Multi-Channel** | Yes (23 channels) | Only Telegram | Others disabled; can be enabled |\n\n---\n\n## Recommendations for Nuzantara\n\n1. **Upgrade to v2026.4.29** (from v2026.3.31): Knowledge Agents system ready; cron scheduler likely fixed; auth profiles stabilized\n2. **Exploit Knowledge Agents**: Build corpus from claude-mem observations; enable conversational history replay (query_corpus tool)\n3. **Fix Cron Scheduler**: Debug Apr 30 freeze; if unresolved in v2026.4.29, fallback to external cron-agent-python runner\n4. **Reduce Telegram Commands**: Disable unused skills (elite-longterm-memory, bluebubbles, discord, slack, spotify, trello) to stay under 100-command limit\n5. **Increase Telegram Timeout**: Raise `timeoutSeconds=120` to mask network latency (or implement webhook polling in next OpenClaw version)\n6. **Monitor Memory Growth**: Track `~/.openclaw/logs/gateway.log` size (currently 21.7 GB); implement log rotation or external log shipping\n7. **Test Voice-Call Skill**: Verify Twilio integration if voice interaction is planned\n8. **Sync Custom Skills**: Ensure `/nuzantara-mcp/skills/` fully registered with OpenClaw (check skills.entries for all custom entries)\n\n---\n\n## Files Referenced\n\n- **Config**: `/Users/nuzantara/.openclaw/openclaw.json` (v2026.3.31 schema)\n- **Installation**: `/Users/nuzantara/.openclaw/lib/node_modules/openclaw/`\n- **Logs**: `~/.openclaw/logs/gateway.log`, `gateway.err.log`\n- **Memory DB**: `~/.openclaw/agents/main/agent/memory.db` (SQLite, not visible in config)\n- **Workspace**: `~/.openclaw/workspace/` (markdown docs + agent state)\n- **Extensions**: `~/.openclaw/extensions/claude-mem/` (installed plugin)\n- **GitHub**: https://github.com/openclaw/openclaw (releases, issues, docs)\n- **Documentation**: https://docs.openclaw.ai (official, updated for v2026.4.29)\n- **claude-mem Marketplace**: `/Users/nuzantara/.claude/plugins/marketplaces/thedotmack/` (v12.1.0, AGPL-3.0)\n\n---\n\n**Document Compiled**: 2026-05-02 13:20 UTC | **Last Config Change**: 2026-05-02 13:20 UTC (Nuzantara-reported version)\n"}}}}