Substantive update focused on observability — making what the agent is doing in autonomous mode visible everywhere it should be, and surfacing the long-tail drift patterns (calcified skill catalog, knowledge search misses, role-gate paralysis) that were quietly costing cycles.
Web — autonomous activity is now first-class
When autonomous mode is running, you used to have to dig into the Mind tab to see anything. Now:
- Dashboard gets a new
Autonomous Activitycard at the top — last 5 mind events, color rails per type (sky/emerald/purple/amber/red),View live →opens the full feed. - Mind page restructured: a full-height chat-shaped live feed is the dominant left column. Auto-scrolls when new events land, stays put when you scroll up, "jump to live" pill returns you. Status / Budget / Config / Scratchpad / Recent Actions become a slim right sidebar.
Skill catalog — telemetry + conditional gating
Logs showed only ~9 distinct skills loaded per 18h cycle out of 178. The catalog was calcifying onto a tiny working set. Two additions:
- Usage sidecar at
data/.skill_usage.jsonrecordsview_count+last_viewed_aton everyskill_read. CLI report:elophanto skills neglectedlists never-viewed first, then oldest. Best-effort writes — telemetry can never break the read. - Conditional gating in
SKILL.mdfrontmatter —requires_tools: [polymarket_get]hides the skill from the catalog when prerequisites aren't loaded;fallback_for_tools: [web_search]hides when the primary IS loaded. Opt-in per-skill; existing skills behave identically until they adopt the fields.
Knowledge search — three-tier cascade
Production was producing 0-result searches even when the KB had matching chunks. Old code only fell through to keyword on a thrown exception; semantic returning [] cleanly would skip the fallback entirely. New flow:
- Semantic search.
- If empty, keyword fallback (was only triggered on exception before — this is the bug fix).
- If still empty AND router available, one LLM rewrite converts the imperative query (
"do a post on X") to topic keywords and retries — bounded to one call per search, no loop.
Every search now leaves one log line with count + score; 0-result hits log as WARNING so they're greppable. search_type label reflects the path that actually produced results (was wrongly labelled semantic when keyword fallback ran inside it).
Role gate — meta tools always allowed
Observed in production: a narrow OPS-role allowlist racked up 240 denials in one 18h cycle, including 14 denied role_use calls — the mind literally could not exit the role. Fixed by exempting a small set of meta / mind-internal / read-only tools (update_scratchpad, set_next_wakeup, role_list, role_use, skill_read, etc.) from the gate. Write tools (company_set_*, shell_execute) stay fully gated.
Chat — resilient placeholder match
Second-message in the web chat sometimes appeared only after refresh. Client now falls back to "most recent streaming agent placeholder" when exact reply_to match fails, so the bubble fills regardless of what the wire sent. Server adds a chat_response: reply_to=... diagnostic log to chase the underlying empty-reply_to bug.
Doctor + setup — tmux preflight
./elophanto doctor now warns when tmux isn't installed (required for swarm orchestration), and setup.sh auto-installs it via brew on macOS.
Other
- OpenEloPhanto teased in README — coming-soon cloud edition framing, same self-host story.
- Numbers refresh: tests 2080 → 2400+, docs 77 → 84+, skills 172 → 178+.
docs/REVENUE.mdcreated ($ELO contract address, pump.fun + Polymarket + payments cross-links).
Upgrading
./update.sh
./start.sh --web # hard-reload the browser to pick up the new MindFeed
The role-gate fix + knowledge_search cascade activate as soon as the Python process restarts. Skill telemetry starts recording on first skill_read after restart — run elophanto skills neglected after a few days to see what's load-bearing vs dead weight.
Full diff: v2026.05.28.1...v2026.05.31