# atlas-mem-poller — Runbook

**Built:** 2026-05-24 by Riv  
**Status:** Live on Minas_Tirith via PM2

---

## What It Does

Polls mem.ai every **10 minutes** for notes updated since the last run, fetches full content for each, and POSTs them into Atlas as `project_events` (source = `"mem.ai"`). The Haiku classifier auto-tags each event to the right project.

---

## Files

| Path | Purpose |
|---|---|
| `C:\PKA\atlas\app\scripts\poll-mem.mjs` | The poller script |
| `C:\PKA\atlas\app\.mem-poll-state.json` | High-water mark cursor (auto-managed) |
| `C:\PKA\atlas\app\ecosystem.config.js` | PM2 process entry (`atlas-mem-poller`) |

---

## PM2 Process

```
Name:     atlas-mem-poller
Script:   scripts/poll-mem.mjs
CWD:      C:\PKA\Atlas\app
Mode:     fork
Restart:  autorestart, max_restarts: 20, min_uptime: 60s, max_memory: 200M
```

### Useful Commands (run in elevated PowerShell on Minas_Tirith)

```powershell
pm2 logs atlas-mem-poller        # Live log stream
pm2 status                       # Check process health
pm2 restart atlas-mem-poller     # Manual restart
pm2 stop atlas-mem-poller        # Pause polling
pm2 reload ecosystem.config.js   # Reload after config changes
```

---

## How It Works

1. Reads `last_polled_at` from `.mem-poll-state.json` (defaults to 24h ago on first run)
2. Calls `GET https://api.mem.ai/v2/notes?filter_by_updated_after=<cursor>&order_by=updated_at&limit=50`
3. Paginates through all results (handles multiple pages)
4. For each note, fetches full markdown content via `GET /v2/notes/<id>?include_content=true`
5. POSTs to Atlas: `POST http://localhost:3000/api/project-events` with `source="mem.ai"`, `external_id=<note_id>`
6. Idempotency: Atlas deduplicates on `(source, external_id)` — safe to re-run
7. Advances cursor, sleeps 10 min, repeats

---

## Atlas Event Shape

```json
{
  "source": "mem.ai",
  "event_type": "note",
  "external_id": "<mem-note-uuid>",
  "actor": "mem.ai",
  "created_at": "<note.created_at>",
  "payload": {
    "title": "Note title",
    "snippet": "First few lines...",
    "content": "# Full markdown content...",
    "collection_ids": [],
    "mem_updated_at": "2026-05-24T...",
    "mem_url": "https://mem.ai/m/<id>"
  }
}
```

---

## Troubleshooting

| Symptom | Check |
|---|---|
| Process offline / restart loop | `pm2 logs atlas-mem-poller` — look for FATAL lines (missing env keys) |
| No notes flowing in | Verify `MEM_API_KEY` in `atlas/.env.local`; test: `curl -H "Authorization: Bearer <key>" https://api.mem.ai/v2/notes?limit=1` |
| Atlas rejecting events | Verify `ATLAS_INGEST_TOKEN` in `atlas/.env.local`; check Atlas is up on port 3000 |
| Cursor stuck / re-deduping | Normal if no new notes — cursor advances when new notes arrive. Check `.mem-poll-state.json` for current timestamp |
| PM2 shows N/A pid + empty logs | CWD misconfiguration. Check `ecosystem.config.js` — cwd must use double backslashes: `'C:\PKA\Atlas\app'` |

---

## Rate Limits / API Notes

- mem.ai v2 API uses `Authorization: Bearer <key>` (NOT `ApiKey`)
- Base URL: `https://api.mem.ai/v2`
- 150ms delay between per-note content fetches (configurable via `MEM_POLL_INTERVAL_MS` env var)
- mem.ai v0 API is deprecated as of 2026 — always use v2

