| 1 | # Darwin Cortex Gateway |
| 2 | |
| 3 | Unified second-brain gateway. One verb: `ask`. Fans out to all memory engines in parallel, reconciles by source-of-truth hierarchy with recency decay, returns ranked hits + receipts + conflict log. |
| 4 | |
| 5 | ## How to run |
| 6 | |
| 7 | ### Development (CT215 local ext4) |
| 8 | |
| 9 | ```bash |
| 10 | cd /var/tmp/darwin-dev/cortex |
| 11 | pip install -r requirements.txt |
| 12 | uvicorn main:app --host 0.0.0.0 --port 9890 --reload |
| 13 | ``` |
| 14 | |
| 15 | State/cache never touches CIFS. The app is stateless; no files written at runtime. |
| 16 | |
| 17 | ### Tests |
| 18 | |
| 19 | ```bash |
| 20 | cd /var/tmp/darwin-dev/cortex |
| 21 | python -m pytest tests/ -v |
| 22 | ``` |
| 23 | |
| 24 | Both test suites must be green before any deploy: |
| 25 | - `tests/test_reconcile.py` - the Hermes regression guard (13 tests) |
| 26 | - `tests/test_smoke.py` - graceful degradation + ranking integration (6 tests) |
| 27 | |
| 28 | ### MCP stdio server (agents) |
| 29 | |
| 30 | ```bash |
| 31 | python /opt/darwin/cortex/mcp_server.py |
| 32 | ``` |
| 33 | |
| 34 | Add to an agent's MCP config: |
| 35 | ```json |
| 36 | { |
| 37 | "mcpServers": { |
| 38 | "darwin": { |
| 39 | "command": "python", |
| 40 | "args": ["/opt/darwin/cortex/mcp_server.py"] |
| 41 | } |
| 42 | } |
| 43 | } |
| 44 | ``` |
| 45 | |
| 46 | ### MCP SSE shim (Cockpit / remote agents) |
| 47 | |
| 48 | ```bash |
| 49 | pip install mcp-proxy |
| 50 | mcp-proxy --port 9891 -- python /opt/darwin/cortex/mcp_server.py |
| 51 | ``` |
| 52 | |
| 53 | Register as: `http://REDACTED-IP:9891/sse` |
| 54 | |
| 55 | ## Deploy to Darwin CT (REDACTED-IP) |
| 56 | |
| 57 | 1. Provision CT252 with Ubuntu 22.04, Python 3.11, pip. |
| 58 | 2. Copy cortex tree: `scp -r /shared/projects/darwin/cortex root@REDACTED-IP:/opt/darwin/cortex` |
| 59 | 3. Install deps: `pip install -r /opt/darwin/cortex/requirements.txt` |
| 60 | 4. Set env vars (in `/opt/darwin/.env` or systemd unit): |
| 61 | - `MEMOS_ACCESS_TOKEN=<memos-api-token>` |
| 62 | - `MEMOS_BASE_URL=https://REDACTED-HOST` (or CT244 direct `http://192.168.1.XX:5230`) |
| 63 | - `DARWIN_QWEN_URL=http://REDACTED-IP:11434/api/chat` (when 3060 is up) |
| 64 | - `DARWIN_ENABLE_OPUS=false` (set true + DARWIN_CLAUDE_API_KEY when ready) |
| 65 | 5. Point engine URLs at CT215 (where the four engines live): |
| 66 | All engine SSE URLs in the adapters default to `127.0.0.1` - override if Darwin CT is separate: |
| 67 | - `RAG_URL=http://REDACTED-IP:9876/sse` |
| 68 | - `CBM_URL=http://REDACTED-IP:9877/sse` |
| 69 | - `SERENA_URL=http://REDACTED-IP:9878/sse` |
| 70 | - `MEMGRAPH_URL=http://REDACTED-IP:9879/sse` |
| 71 | (Or run behind mcp-proxy SSE bridges on CT215 and point there.) |
| 72 | 6. Create systemd unit: |
| 73 | ```ini |
| 74 | [Unit] |
| 75 | Description=Darwin Cortex Gateway |
| 76 | After=network.target |
| 77 | |
| 78 | [Service] |
| 79 | WorkingDirectory=/opt/darwin/cortex |
| 80 | ExecStart=uvicorn main:app --host 0.0.0.0 --port 9890 |
| 81 | Restart=always |
| 82 | EnvironmentFile=/opt/darwin/.env |
| 83 | |
| 84 | [Install] |
| 85 | WantedBy=multi-user.target |
| 86 | ``` |
| 87 | 7. `systemctl enable --now darwin-cortex` |
| 88 | |
| 89 | ## Architecture notes |
| 90 | |
| 91 | - `/ask` fans out to up to 5 engines in parallel, each with a 4s hard timeout. |
| 92 | - Ranking: `score = w_authority * recency_decay * confidence * relevance` |
| 93 | - `recency_decay = exp(-age_days/30)` - the Darwin valve that makes stale agent-memory lose to fresh live-infra facts. |
| 94 | - LLM synthesis: tries qwen3:8b on 3060 first; falls back to deterministic ranked-merge (always works). Opus gated behind env flag. |
| 95 | - MCP tool `darwin_ask` wraps `/ask` for agent consumption. SSE shim on :9891 via mcp-proxy. |
| 96 | - All state on local ext4 (`/var/tmp/darwin`). Never on CIFS. |