DHA Core — Codebase Review
Repo: NightKnight64/dha-core
Reviewed: 2026-04-25
Location: /home/hoffmann_admin/dha-core-legacy
Size: 10 Python files, 716 lines total
State: Archived / deprecated — superseded by family-assistant and hoffdesk-agents
1. Architecture
DHA Core is an abstract service mesh framework — not a shipping family assistant. It defines a plugin architecture where modules implement a DHA_Module ABC, are registered via Service_Manifest.yaml, and executed by an Orchestrator with an in-process BackgroundScheduler. There's an EventBus for pub/sub between modules and a YAML-based identity/role system.
Component Map (716 total lines)
┌─────────────────────────┐
│ Service_Manifest.yaml │ (4 services)
└─────────┬───────────────┘
│
┌─────────▼───────────────┐
│ Orchestrator.py (161) │ ── YAML loader
│ │ ── Dynamic import + init
│ │ ── APScheduler loop
└─────────┬───────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
┌───────▼───────┐ ┌────────▼───────┐ ┌─────────▼──────┐
│ Persistence │ │ Identity │ │ CalendarSync │
│ Module (105) │ │ Module (95) │ │ Module (98) │
│ - SQLite │ │ - household.yaml│ │ - Adapter │
│ - state save │ │ - RBAC │ │ Pattern │
└───────┬───────┘ └────────┬───────┘ └─────────┬──────┘
│ │ │
│ ┌─────────▼───────┐ ┌─────────▼──────┐
│ │ Notification │ │ GoogleAdapter │
│ │ Module (44) │ │ (simulated) │
│ │ - EventBus │ └────────────────┘
│ │ subscriber │
│ └─────────┬───────┘
│ │
└───────────────────────┘
EventBus (12 lines)
Supporting infrastructure:
├── DHA_Module.py (22) ── Abstract Base Class
├── event_bus.py (38) ── Pub/Sub (in-memory)
├── debug_smore.py (28) ── Debug launcher
└── smore_test.py (100) ── Integration test / demo
Architecture Assessment ✅ Good abstraction, poor implementation
The abstract framework is well-conceived:
- Plugin pattern via ABC + YAML manifest → genuinely extensible
- EventBus provides loose coupling
- Adapter pattern for calendar providers (though only Google is implemented and it's mocked)
- background.Scheduler for recurring tasks
But it's all scaffolding and no building:
- The Google adapter returns hardcoded mock data
- The Notification module just prints to terminal
- The Identity module loads from YAML but never checks permissions in a real request
- No real API endpoints, no Telegram/webhook integration
- Service_Manifest.yaml is in .gitignore (intentionally omitted for deployment)
2. Code Quality
What's Good
- Clean abstract interface.
DHA_Modulewithinitialize(),check_status(),execute_task()is a solid contract. - EventBus is minimal and correct. 38 lines, no external deps, works.
smore_test.pyis a working integration test. It spins up the orchestrator, initializes all four modules, runs a loop — genuine end-to-end smoke test (albeit with mocked adapters).__pycache__is gitignored. Small win, but consistent.
What's Not
- Google adapter returns hardcoded fake data. The comment says "Simulated API call" — this is a stub, not production code. The
api_keyconfig parameter is accepted but never used. - No actual HTTP/API layer. No FastAPI, no Flask, no webhook. DHA Core can't receive or send anything — it's a local-only scheduler with
print()statements as output. sys.path.appendin every module. All four modules have the exact same boilerplate:sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))). Should be a one-line setup.py / PYTHONPATH fix.household.yamlincludes Maggie the dog as astandardrole user. Cute, but the RBAC layer has a canine member withpreferences.notifications: false— which is correct, but it's an indication the design is playful rather than production.smore_test.pyhastime.sleep(4)polling. The scheduler should call back; blocking sleeps are not how you test an event loop.- No error recovery. If a module fails to initialize, the orchestrator logs it but continues. No circuit breaker, no retry, no alert.
- The
PersistenceModulesaves JSON state but nothing reads it. It's write-only storage.
3. Feature Completeness vs What It Should Have Been
| Feature | Status | Family Assistant Equivalent |
|---|---|---|
| Plugin module system | ✅ Built | Not needed (single app) |
| EventBus pub/sub | ✅ Built | Not used |
| YAML identity + RBAC | ✅ Built | YAML config in config.py |
| Calendar fetch (Google) | 🔶 Stubbed | 660 lines, Radicale CalDAV |
| Notification | ❌ print() only | 602 lines, Telegram Bot API |
| Email parsing | ❌ Missing | 1148-line pipeline |
| LLM extraction | ❌ Missing | appointment_parser.py |
| Conflict resolution | ❌ Missing | 415-line conflict_engine.py |
| Webhook / HTTP | ❌ Missing | 252-line email_webhook.py |
| Family Brain / RAG | ❌ Missing | 495-line family_brain.py |
| Clicker / slot tracking | ❌ Missing | 303-line clicker.py |
| Maintenance reminders | ❌ Missing | 376-line maintenance_sentinel.py |
| Tests | 🔶 1 integration demo | 1 test file (test_qa.py) |
4. Relationship to Family Assistant
DHA Core was the prototype that taught you the patterns that became Family Assistant. Specifically:
- Learned: Abstract module frameworks (DHA_Module) add complexity without value for a single-app deployment. Family Assistant doesn't use it — it's a flat Python package.
- Learned: Hardcoded adapter patterns (GoogleAdapter) are worse than YAML-driven config. Family Assistant uses
config.pywith env vars and family.yaml. - Learned: In-process EventBus is overengineered for a notification system that just needs HTTP. Family Assistant uses direct Telegram API calls.
- Learned: The plugin manifest adds deployment friction without the benefit of hot-plugging. Family Assistant is a pip-installable package.
The calendar_sync module in DHA Core (98 lines, mocked) became the 660-line radicale-driven calendar_sync.py in Family Assistant. The identity module (95 lines, YAML-only) became the config.py family.yaml loader (369 lines with env, caching, dynamic grading). The notification module (44 lines, print()) became hermes.py (602 lines, Telegram Bot API).
DHA Core is best understood as a "proof of concept" that you evolved past. The architecture decisions (service mesh, abstract modules, EventBus) are the right patterns for a multi-service distributed system, but for a single-machine family assistant they were overengineering.
5. Portability: 5/10
- Requirements:
PyYAML==6.0.3(+ Python stdlib). That's it. - No external deps: No FastAPI, no httpx, no Ollama, no CalDAV libraries, no databases beyond SQLite.
- BUT: It doesn't do anything useful without external services. The Google adapter is stubbed. There's no webhook to receive events. The notification module doesn't connect to anything.
- Verdict: Portable by virtue of being incomplete. Running it gives you a scheduler that prints to stdout.
6. Assessment Summary
| Dimension | Score | Notes |
|---|---|---|
| Architecture Concept | 8/10 | Abstract module system is well-designed |
| Actual Implementation | 3/10 | All adapters stubbed, no real I/O |
| Code Quality | 6/10 | Clean ABC, but sys.path.append everywhere |
| Feature Completeness | 2/10 | Framework only, no shipping features |
| Portability | 5/10 | Minimal deps, but useless without wiring |
| Evolution Value | 7/10 | Taught valuable lessons that shaped Family Assistant |
Historical Significance
This was the original blueprint — the architecture you sketched before you wrote a single line of Family Assistant. The fact that it evolved into a 10k-line working system that processes real email, syncs to a real calendar, and runs on your hardware is genuinely impressive. The DHA Core framework (Service_Manifest, DHA_Module ABC, EventBus) was the right starting point, and Family Assistant is the right destination.
Recommendation: Delete the dha-core GitHub repo or archive it with a clear README note that says "Historical prototype — superseded by NightKnight64/family-assistant." The abstract framework is interesting but misleading as a starting point for anyone who finds it.
Family Assistant (Standalone) — Codebase Review
Repo: NightKnight64/family-assistant
Reviewed: 2026-04-25
Location: /home/hoffmann_admin/.openclaw/workspace/scripts (+ cloned in hoffdesk-agents/services/family_assistant)
Size: ~10,385 lines across 24 Python modules + 7 prompt files + pyproject.toml
State: Production. Serving real traffic via Cloudflare webhook on hook.hoffdesk.com.
Note: This is the same codebase reviewed in-depth in hoffdesk-agents-review.md. The key findings are summarized here with a focus on differences from the mono-repo copy.
Key Finding: Near-Identical to hoffdesk-agents Version
The standalone family-assistant repo and the version embedded in hoffdesk-agents/services/family_assistant are essentially the same code:
- 22 of 24 Python files are byte-for-byte identical
- hermes.py differs (standalone: 602 lines, mono-repo: 666 lines — likely OpenClaw integration hooks)
- pipeline.py differs by 1 byte (trivial)
- Same prompts, same tests, same structure
However, the standalone repo has important artifacts that the mono-repo doesn't:
- systemd/ directory with actual service files (family-assistant-webhook.service, hoffdesk-webhook.service, radicale.service)
- WEBHOOK_DEPLOY.md — deployment docs for the Cloudflare Worker
- email_worker.js — the Cloudflare Email Worker that routes mail to the webhook
- LICENSE (MIT) — the mono-repo doesn't have one
- backup_hoffdesk.sh — backup script
- .env file (real credentials — still live)
- Legacy wrappers (family_calendar.py, fetch_unread.py)
Critical Finding: .env is Committed-Adjacent
The .env file in the standalone repo (/home/hoffmann_admin/.openclaw/workspace/scripts/.env) contains:
- GMAIL_APP_PASSWORD (live Gmail password)
- GOOGLE_PLACES_API_KEY (live)
- CALDAV_PASSWORD (Radicale credentials)
- TELEGRAM_BOT_TOKEN (live bot token)
- WEBHOOK_SECRET (live webhook shared secret)
- OLLAMA_EMBED_URL (hardcoded to Gaming PC Tailscale IP)
- OPENAI_API_KEY (if configured)
It's gitignored, but it lives inside the tracked project tree. The hoffdesk-agents version has the same .env in services/.env. If you ever clone with --include-untracked, force-push a branch that includes it, or accidentally stage it with git add ., those credentials are in git history permanently.
Recommendation: Rotate all six credentials, then move .env to ~/.openclaw/secrets/family-assistant.env. Update the systemd EnvironmentFile paths accordingly.
Family Assistant vs DHA Core: The Evolution
| Dimension | DHA Core | Family Assistant |
|---|---|---|
| Philosophy | Abstract framework | Concrete application |
| Architecture | Service mesh + EventBus | Flat package + direct calls |
| Calendar | Google Calendar (mocked) | Radicale CalDAV (self-hosted) |
| Email ingress | None | Cloudflare Webhook + IMAP fallback |
| LLM | None | Ollama (qwen2.5-coder:7b) |
| RAG | None | ChromaDB + nomic-embed-text |
| Notification | print() | Telegram Bot API + inline buttons |
| Tests | 1 integration demo | 1 smoke test (test_qa.py) |
| Real users | 0 | 2 (Matt + Aundrea) |
| Lines of Python | 716 | ~10,385 |
| External API deps | 0 | 1 (Google Places — optional) |
| Git commits | 5 | ~20 |
The evolution is clear: DHA Core taught you the patterns. Family Assistant built the product. Both have near-zero test coverage and sys.path/import quirks, but Family Assistant actually ships real value.
Key Findings Summary
Critical (fix immediately)
- Rotate all credentials in
.envand move the file to~/.openclaw/secrets/ appointment_retry.txtis empty (0 lines) — the LLM retry path sends a blank prompt- Gaming PC hardcoded as the only embedding + vision host — if it's off, the Brain and document scanning break silently
High Priority
- No tests for 23/24 modules — any refactoring is blind
- Pipeline has ~500 lines of duplicated code (IMAP path vs webhook path)
hermes.pyhas dual notification paths (direct Telegram API + OpenClaw subprocess) — potential for duplicate sends- Family assistant standalone has a cleaner
.gitignorewithfamily.yaml,maintenance.yaml,chroma_db/,locations/, andauth_circuit_breaker.jsonignored — the mono-repo version should adopt these patterns
What's Actually Great
config.pyis production-quality: centralized, cached, dynamic family context injectionrrule_builder.pyprevents LLM hallucination on recurrence rules (deterministic Python → RFC 5545)- Circuit breaker on IMAP auth failures prevents notification spam during outages
- Shadow filtering (rejection_engine.py) events are demoted, not deleted — user sees what was filtered
- Prompt-as-Code pattern — prompts in text files, not Python. Easy to iterate without touching code.
- Hybrid Retrieval (calendar + ChromaDB) is the smartest architectural decision in the codebase