# MEMORY.md β€” Long-Term Memory ## Identity - I am **Socrates** 🧠 β€” Lead AI Systems Architect - Vibe: efficient, competent, dry humor. Jarvis energy. ## Matt - Head of household: wife Aundrea, kids Sullivan & Harper, dog Maggie - Green Bay, WI β€” America/Chicago timezone - Values: security, zero-trust, doing things right before scaling ## Infrastructure - **titanium-butler** (Beelink): Ubuntu 24.04, loopback-only gateway (port 18789), token auth - Primary model: `ollama/glm-5.1:cloud` β†’ fallbacks: kimi-k2.5:cloud, gemma4:latest, qwen2.5-coder:7b - Local Ollama at 127.0.0.1:11434 β†’ Ollama Pro cloud - OpenClaw features: Dreaming (3 AM CST), Active Memory (direct DMs), command-logger hook, lightContext heartbeat - **Gaming PC** (Tailscale 100.104.147.116): 12GB 3080 Ti - qwen2.5-coder:7b (default pipeline model), gemma4:latest, qwen3-vl:8b (vision/OCR), nomic-embed-text (embeddings) - **Secrets**: All in `~/.openclaw/.env` and `scripts/.env` (chmod 600, gitignored, never pushed) - **Telegram**: DMs allowlisted (8386527252), family group allowFrom Matt only ## Family Assistant β€” v1.0 Feature-Frozen - **Repo**: https://github.com/NightKnight64/family-assistant (MIT, PII scrubbed 2026-04-16) - **Package**: `scripts/family_assistant/` β€” 18 modules, full docs in README - **Config**: `scripts/.env` (env vars) + `scripts/family.yaml` (gitignored) + `~/.openclaw/secrets/gcal-service-account.json` - **LLM parsing**: qwen2.5-coder:7b on Gaming PC via LLM_URL β€” zero cloud tokens - **Embeddings**: nomic-embed-text on Gaming PC β†’ ChromaDB on Beelink (`~/.family_assistant/chroma_db/`) - **Vision**: qwen3-vl:8b on Gaming PC (Drop-Box only, `keep_alive: 0`) - **Location cache**: `~/.family_assistant/locations/known_locations.json` (home-biased, 90-day TTL) ### Key Pipelines - **Emailβ†’Calendar**: IMAP fetch β†’ LLM parse β†’ Google Calendar CRUD β†’ Telegram push (Hermes) - **Intent Engine**: Wake word/reply-to-bot β†’ LLM classification (calendar/question/chatter) β†’ execute or RAG or silence - **Family Brain (RAG)**: ChromaDB semantic retrieval + Calendar keyword search β†’ LLM synthesis (retrieval-only) - **Conflict Engine**: Detect overlaps β†’ LLM resolution options β†’ Telegram inline buttons (SPLIT/REASSIGN/RESCHEDULE) - **Rejection Engine**: Natural language β†’ LLM rule β†’ shadow filter (downgrade, never delete) β†’ persistent in family.yaml - **Maintenance Sentinel**: Recurring tasks with intervals β†’ alert dedup β†’ Done buttons - **Clicker + Slots**: Jina Reader fetch β†’ LLM slot extraction β†’ inline buttons β†’ [REMINDER] calendar event on tap - **Document Sorter**: Telegram image β†’ OCR (qwen3-vl:8b) β†’ LLM classify β†’ Google Drive upload (flat year folders) ### Hermes Routing (Trust Over Silence) - **Family Group**: appointments, reminders, actions, conflicts, newsletter digest, daily brief - **Matt's DM**: auto-filtered items, pipeline errors, system health, research results - **Philosophy**: silence = distrust; users need visual confirmation ### Critical Design Rules - Date disambiguation: nearest logical future date (not distant future) - Conflict anti-nag: [Conflict_Ack] tags + dismiss button - Shadow filter: rejected items downgraded (low_relevance), never deleted - Intent guardrail: trigger-based ONLY (wake word/reply-to-bot), NO passive listening - Global error handler: all crashes β†’ DM stack trace, no silent deaths - HTMLβ†’text: stdlib only (html.parser), no BeautifulSoup/lxml - Pipeline idempotency: ChromaDB uses `.upsert()`, Calendar uses dedup - Year display: show year only when event year β‰  current year ### Permanent Model Rules - βœ… qwen2.5-coder:7b β€” single model for ALL pipeline tasks (beat phi4:14b on quality + speed) - βœ… qwen3-vl:8b β€” vision/OCR only (Drop-Box), `keep_alive: 0` - β›” No `home-assist` model β€” ever - β›” No `deepseek-r1` models β€” burn thinking tokens, fail JSON - β›” No `qwen3:8b` β€” thinking tokens can't be disabled, 3-13x slower ### CLI Quick Reference - `process [--dry-run]` β€” emailβ†’calendarβ†’Telegram - `upcoming [--hours N]` β€” list calendar events - `conflict-notify` β€” scan + alert on new conflicts - `intent --message '...'` β€” parse + execute calendar mutation - `maintenance` β€” check recurring tasks - `reject 'event' 'reason'` β€” add rejection rule - `brain-query --question '...'` β€” RAG query - `click --url '...' --context '...'` β€” fetch signup slots ## Radicale CalDAV β€” Self-Hosted Calendar (2026-04-18) - **Radicale 3.7.1** on Beelink: `0.0.0.0:5232` (localhost + Tailscale) - **htpasswd**: `/home/hoffmann_admin/.config/radicale/htpasswd` β€” bcrypt, 3 users (matt, aundrea, assistant) - **Rights**: `/home/hoffmann_admin/.config/radicale/rights` β€” all-authenticated-read-write (private network) - **Storage**: `/home/hoffmann_admin/.local/share/radicale/collections/` - **Family calendar**: "family" (owned by `assistant` user) - **Passwords**: `family-matt-2026`, `family-aundrea-2026`, `family-assistant-2026` - **calendar_sync.py** completely rewritten: caldav+icalendar, zero Google API - **All downstream modules updated**: intent_engine, conflict_engine, conflict_notify, rejection_engine, slot_handler, cli - **pipeline.process_webhook_email()** wired: webhook β†’ LLM extraction β†’ Radicale write β†’ Hermes - **Commit**: `a8f32d1` pushed ## The Board β€” Triple-Agent Architecture (2026-04-20) - **Socrates 🧠** β€” Backend, pipelines, infra, AI architecture (this is me) - **Daedalus 🎨** β€” Frontend, UI/UX, design system, mobile - **Wadsworth πŸ“‹** β€” Chief of Staff, routing, scheduling, general assistance - **Matt** β€” The Director. Sets priorities, approves designs, owns the domain. - **Collaboration**: Contract-first β€” I write API specs, Daedalus builds UI, Wadsworth routes and coordinates, Matt approves - **Shared workspace**: `/home/hoffmann_admin/.openclaw/shared/` (api-specs/, design-tokens/, project-docs/) - **Daedalus workspace**: `~/.openclaw/workspace-daedalus/` (separate identity, same gateway) - **Wadsworth workspace**: `~/.openclaw/workspace/` (main agent, coordination hub) - **Daedalus model**: `ollama/gemma4:26b` (separate model for creative diversity) - **Socrates model**: `ollama/kimi-k2.5:cloud` (reasoning-focused for architecture) - **Wadsworth model**: `ollama/glm-5.1:cloud` (generalist, coordination) ### Inter-Agent Comms Protocol - βœ… `sessions_send` or `sessions_spawn` for agent-to-agent messaging - ❌ NEVER use Telegram API to message agents (causes identity confusion) - `shared/` directory for async file-based coordination - Telegram @mention for Boardroom discussions where Matt is present ## Architecture Principles - **Prompt-as-Code**: Route messy human data to LLM, never regex - **Tri-Node**: Beelink = orchestration; Gaming PC = inference; Cloud = deep reasoning only - **Zero-Trust**: App Passwords > OAuth. localhost/Tailscale only. No global npm -g with native bindings. - **Maintenance > Compute**: A prompt is easier to update than a regex library - **Contract-First**: API spec β†’ UI mock β†’ approval β†’ real wiring (prevents race conditions) ## OpenClaw Config (2026-04-18 Audit) - **Active**: Dreaming (3 AM CST), command-logger hook - **Active Memory**: DISABLED (2026-04-20) β€” was blocking responses on slow models, causing generic output. Config preserved with `llama3.2:1b-instruct-q4_K_M` for future local recall. - **Heartbeat**: lightContext + isolatedSession + activeHours 06:00-23:00 CST (~95% token savings) - **Fallback chain**: glm-5.1:cloud β†’ kimi-k2.5:cloud β†’ gemma4:latest β†’ qwen2.5-coder:7b - **Logging**: redactSensitive: "tools" - **Experimental**: sessionMemory (indexes session transcripts for recall) - **Wiki**: isolated vault at `~/.openclaw/wiki/main/` - **Agent health playbook**: `shared/project-docs/agent-health/troubleshooting-playbook.md` - **Critical lesson**: Auto-failover can permanently override agent model at session level β€” causes identity loss. See playbook. - **Bookmark**: Check `command-logger.jsonl` size in ~1 month, add logrotate if needed ## Roadmap - [x] v1.0 PENCILS DOWN (2026-04-17) β€” all core features shipped - [x] OpenClaw features audit β€” 5 quick wins applied (security, heartbeat, fallback, hooks, memory) - [x] Radicale CalDAV migration β€” Google Calendar API completely replaced (2026-04-18) - [x] calendar_sync.py rewrite β€” caldav+icalendar, all modules updated - [x] pipeline.process_webhook_email() β€” webhook β†’ Radicale writes (2026-04-18) - [x] Radicale running on Beelink (0.0.0.0:5232, htpasswd bcrypt, 3 users) - [x] **systemd services** β€” radicale.service + hoffdesk-webhook.service installed & running - [x] **Cloudflare Email Worker** β€” deployed, WEBHOOK_SECRET set, Email Routing active for assistant@hoffdesk.com - [x] **Sovereign backup** β€” daily tar to local + Gaming PC via Tailscale SSH - [x] **Phone CalDAV setup** β€” both Matt & Aundrea on assistant account via cal.hoffdesk.com - [ ] Auth failure circuit breaker (3 consecutive β†’ pause + alert) - [ ] Drop-Box Drive setup (Drive API + folder share + DRIVE_FOLDER_ID) β€” blocked on Google - [ ] Wire Telegram image interception for Drop-Box - [ ] Multi-calendar, Docker Compose, YAML prompts (deferred post-v1.0) - [x] Fix conflict_notify.py NameError (RESOLVED by calendar_sync rewrite) - [x] Get Aundrea set up to email family manager (CalDAV live, email worker live) - [x] **Daedalus agent initialized** β€” workspace, SOUL.md, IDENTITY.md, onboarding doc (2026-04-19) - [ ] Telegram bot token for Daedalus (Matt handling) - [x] Daedalus agent added to openclaw.json + bindings - [x] **Wadsworth identity fix** β€” added `main` agent to openclaw.json, reset contaminated session (2026-04-19) - **Lesson**: Never operate as Socrates through the main/default bot β€” it contaminates Wadsworth's session history with wrong identity context. Always use the Socrates bot for Socrates work. - [x] "The Hoffmann Board" Telegram group created - [x] API specs for Family Dashboard β†’ `shared/api-specs/` - [x] HoffDesk Family Dashboard MVP (calendar + health + quick-add) - [x] **Blog module Phase 1+2** β€” Core API + Admin API complete (36/36 tests passing) (2026-04-20) - [x] **Blog module Phase 3** β€” Static generation + deploy COMPLETE (2026-04-20) - [x] **Blog module Phase 4 Backend** β€” Admin preview + list endpoints, 41/41 tests (2026-04-20) - Added `POST /admin/posts/preview` β€” Markdownβ†’HTML live preview - Added `GET /admin/posts` β€” Admin list with `?status=` filter (draft/published/archived/all) - Response doc: `shared/project-docs/blog/phase-4-socrates-response.md` - [x] **LocalAI Content Engine** β€” phi4:14b on Gaming PC (2026-04-20) - Sovereign Operator voice (technical, pragmatic, direct) - Banned words: delve, tapestry, moreover, leveraging, holistic, paradigm, synergy, etc. - Three endpoints: - `POST /admin/generate/title` β€” 3-5 title options from bullets - `POST /admin/generate/expand` β€” Bullet points β†’ prose (augmented drafting) - `POST /admin/generate/seo` β€” Excerpt, tags, meta description - [x] **Blog module Phase 4 Frontend** β€” Admin UI templates deployed 2026-04-22, API integration complete (requires service restart) - [ ] Restart hoffdesk-web service to activate new templates ## Market Sentiment Briefing β€” Complete βœ… (2026-04-27) **System:** Finnhub API integration for daily market sentiment briefing **Free tier:** 60 calls/minute, 4 calls per ticker (quote, sentiment, recommendations, earnings) **Default watchlist:** AAPL, MSFT, GOOGL, AMZN, TSLA, NVDA, META, JPM ### Components - `core/market/sentiment.py` β€” Finnhub API client + briefing generator (246 lines) - `core/handlers/market_briefing.py` β€” Telegram command handlers (`/briefing`, `/watchlist`) - `jobs/daily_briefing.py` β€” Cron job entrypoint for scheduled delivery ### Features - Daily briefing at 3:00 PM CT (market close) - On-demand via `/briefing` command - Watchlist management via `/watchlist` and `watchlist TICKER ...` - Signal detection: analyst consensus + insider sentiment - Alerts: earnings surprises >10%, analyst changes β‰₯2 buys ### Commands | Command | Description | |---------|-------------| | `/briefing` | Generate and send market briefing | | `/watchlist` | Show current watchlist | | `watchlist TICKER ...` | Update watchlist | ### Documentation - `shared/project-docs/market-briefing-system.md` β€” Full system docs ## Icarus Project **Location:** `~/.openclaw/workspace/services/icarus/` **Status:** Phase 5 (Real World) ### Phase 5 Components - [x] **Data Abstraction** β€” `hoffmann.yaml` + deterministic inference engine - [x] **System State View** β€” API + HTML dashboard with HTMX polling - [x] **Memory System Port** β€” ChromaDB + embeddings, zero costco_route imports - [x] **Recipe Toggle System** β€” Extractor + database + Telegram handlers - [x] **Market Sentiment Briefing** β€” Finnhub API + daily briefing - [ ] Telemetry wiring (waiting on real email data) - [ ] UAT (waiting on Matt) ## Blog Module Phase 4 Frontend β€” Deployed βœ… (2026-04-22) **Frontend:** Daedalus templates + admin UI deployed to `/home/hoffmann_admin/hoffdesk/blog/` **Backend:** Admin dashboard API endpoints added (`/admin/stats`, `/admin/recent`, `/admin/posts`, `/admin/images`) **Service:** Running from workspace-socrates, needs reload for new routes **Tests:** All API endpoints verified ### Files Deployed - 7 Jinja2 templates β†’ `/home/hoffmann_admin/hoffdesk/blog/templates/` - Admin templates β†’ `/home/hoffmann_admin/hoffdesk/blog/admin/templates/` - Static CSS β†’ `/home/hoffmann_admin/hoffdesk/blog/static/` ### API Endpoints Added ``` GET /admin/stats β†’ Dashboard statistics GET /admin/recent β†’ Recent activity feed GET /admin/posts β†’ Admin post list with filtering GET /admin/images β†’ Image manager ``` ### Next Step The running service is in `/workspace-socrates/` directory. New routes are added there. Service needs a process restart to pick up new code: ```bash pkill -f "uvicorn main:app" && cd ~/.openclaw/workspace-socrates/hoffdesk-api && nohup uvicorn main:app --host 127.0.0.1 --port 8000 & ``` --- ## Archived History - See `memory/2026-04-15.md` and `memory/2026-04-16.md` for detailed progress logs - Key outcomes already reflected in sections above ## Promoted From Short-Term Memory (2026-04-23) - # 2026-04-16 ## Family Assistant β€” Major Progress ### Response Handler Built - `execute_resolution()` in `conflict_engine.py` β€” split/reassign/reschedule actions - `handle` CLI command: `family_assistant handle --option N [--dry-run]` - Tested all three actions end-to-end against live calendar ### Package Refactor (Archimedes v4) - Monolith `family_calendar.py` β†’ `family_assistant/` package (10 modules) - Externalized 3 prompts to text files with `{today}`, `{family_members}`, `{nickname_rules}` placeholders - Legacy wrapper preserved (3-line import shim) ### De-personalization (Archimedes v5) - Family members β†’ `family.yaml` (configurable per household) - Prompt injection via `{family_members}` and `{nickname_rules}` placeholders - Setup wizard: `python -m family_assistant setup [--non-interactive]` - `family.yaml.example` as public template ### Post-Archimedes Fixes - Service account key fallback chain (env var β†’ CWD β†’ ~/.openclaw/secrets/ β†’ ~/.config/family-assistant/) - `.env` auto-load in config.py for cron/heartbeat sessions - Created `scripts/.env` and `scripts/family.yaml` ## OpenClaw - Updated to 2026.4.15 - Removed unsafe `ollama/gemma4:31b-cloud` from fallbacks ## Heartbeat Setup - `heartbeat:check` β€” every 30 min, system/weather/disk checks - `heartbeat:daily` β€” 7:00 AM CST, security audit + memory/wiki maintenance + update check [score=0.803 recalls=8 avg=0.396 source=memory/2026-04-16.md:1-32] - - Admin auth is CF Access at the edge β€” FastAPI trusts headers, no auth middleware needed ### Wired into main.py: - Blog router mounted at `/api/blog` with CORS updated for POST/PATCH/DELETE - Draft blog post seeded: `the-night-i-broke-dns` ### Test results: 36/36 passing - Public read: list, get, related, categories, tags - Admin write: create, update, delete (soft), publish, unpublish - Full workflow: createβ†’publishβ†’readβ†’updateβ†’archive ### Next: Phase 2 (Admin API + auth) and Phase 3 (static generation with Daedalus' templates) [score=0.801 recalls=8 avg=0.417 source=memory/2026-04-20.md:21-32] ## Promoted From Short-Term Memory (2026-04-27) - # 2026-04-15 β€” Day One ## Onboarding & Security Hardening - **OpenClaw updated** from 2026.4.11 β†’ 2026.4.14 - **UFW firewall configured**: default deny inbound, allow outgoing. SSH (22) + web UI (18789) on tailscale0 only, loopback allowed - **Ollama on Gaming PC** (100.104.147.116): bound to Tailscale IP only, not 0.0.0.0 - **Beelink Ollama fixed**: was crash-looping due to wrong OLLAMA_HOST override (pointed at Gaming PC IP instead of own). Fixed to 0.0.0.0:11434 - **Two-tier model routing established**: - `ollama/glm-5.1:cloud` β€” daily driver (Ollama Pro cloud via local proxy) - `ollama-remote/gemma4` β€” lightweight tasks on Gaming PC 3080 Ti via Tailscale - **Telegram group security (CRITICAL) fixed**: added `allowFrom: ["8386527252"]` to group wildcard, per-group extensible for future - **Security audit**: 0 critical, 3 warn (all acceptable/by design) - **Plugin integrity**: openclaw-web-search now has pinned version + integrity hash ## Identity - I am **Socrates** 🧠 β€” head thinker, lead agent - Vibe: efficient, competent, dry humor (Jarvis energy) - Matt: household head, wife Aundrea, kids Sullivan & Harper, dog Maggie - Location: Green Bay, WI (CST) - Vision: multi-agent setup, I'm the first/coordinator ## Still Open - Sandbox/workspaceOnly settings before adding other users - Pinning plugin spec to exact version - Web UI access over Tailscale (port 18789 allowed but not tested) - node-llama-cpp local embeddings (deferred, using nomic-embed-text via Gaming PC) ## Email + Calendar Pipeline (Phase 2 β€” DONE) [score=0.834 recalls=7 avg=0.403 source=memory/2026-04-15.md:1-31] ## Promoted From Short-Term Memory (2026-04-29) - - Updated CNAME to point to working tunnel `hoffdesk-dashboard-api` - Webhook endpoint now live: https://hook.hoffdesk.com/health ### Remaining tasks (requires Cloudflare dashboard) 1. **Email Routing** β€” Add `assistant@hoffdesk.com` as destination, create routing rule 2. **Deploy Worker** β€” Script ready at `scripts/email_worker.js` (domain updated to hoffdesk.com) 3. **Test end-to-end** β€” Send test email, verify webhook payload, verify classification pipeline ### Key detail - Env var `WEBHOOK_SECRET` = `zFpeh8bKGsWrXAPcrEzRkAPFlo_c7ZOYNTaLKxzAEobwnEiZ9SfOvdTysTkrM4Qr` - Webhook target: `https://hook.hoffdesk.com/webhook` - Worker script already updated: `assistant@hoffdesk.com` **Note:** Email pipeline v2 (classification + routing) is complete and waiting. This is the last mile. [score=0.825 recalls=5 avg=0.417 source=memory/2026-04-23.md:185-199] ## Promoted From Short-Term Memory (2026-04-30) - Created `/family/` module with domain separation: [score=0.806 recalls=0 avg=0.620 source=memory/2026-04-23.md:6-6] - **Working endpoints:** [score=0.806 recalls=0 avg=0.620 source=memory/2026-04-23.md:13-13] - Integrated `shared/grounding.py` to extract real struggles from memory files: [score=0.806 recalls=0 avg=0.620 source=memory/2026-04-23.md:20-20] - **Key grounding sources:** [score=0.806 recalls=0 avg=0.620 source=memory/2026-04-23.md:26-26] ## Promoted From Short-Term Memory (2026-05-01) - **Decision locked:** Session cookies for browsers, Bearer tokens for machines. Documented at `shared/project-docs/auth-unification.md` [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:5-6] - | Before | After | |--------|-------| | X-Admin-Token header | Session cookie (`hoffdesk_session`) | | ?token= query param | Session cookie (unified login) | [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:10-13] - | X-Hoffdesk-Secret | Bearer token for API/webhooks | | /admin/family/login (dead route) | Wired to unified auth system | [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:14-15] - | User | Password | Email | Roles | |------|----------|-------|-------| | matt | `hoffdesk-matt-2026` | matt@hoffdesk.local | admin, editor | | aundrea | `hoffdesk-aundrea-2026` | aundrea@hoffdesk.local | family | [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:25-28] - Browser β†’ /auth/login β†’ Session cookie set β†’ 30 day lifetime [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:33-33] - Automatic redirect to original page [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:35-35] - All /admin/* routes check session cookie [score=0.869 recalls=0 avg=0.620 source=memory/2026-04-24.md:37-37]