# OpenClaw → Echo-Core Migration Playbook

> **Status: EXECUTED 2026-04-21 10:04 UTC.** See "Post-migration state" below.
> This playbook is kept as a living reference for rollback + cleanup.

Run this after the PR `feat/openclaw-consolidation-2026-04` has merged to master.
Estimated downtime: 5–10 minutes. Rollback path at the bottom.

---

## Post-migration state (reference for rollback)

**Migration date:** 2026-04-21 10:04 UTC
**Downtime window:** ~2 minutes (10:02–10:04 UTC)

### Git SHAs
- **Pre-migration master tip:** `4e78ef7` ("claude gstack") — rollback target if everything goes wrong.
- **Post-merge master tip:** `d741541` ("test(dashboard): cover constants, git helper, cron endpoint, files sandbox") — last commit of the migration PR.
- **Current origin/master:** moved forward as Marius tested dashboard commit button post-cutover.

### Backups
- **`/home/moltbot/clawd-backup-2026-04-21/`** — full copy of `clawd/dashboard` (807K) + `clawd/memory` (11M) taken during pre-flight step 3. Keep until 2026-05-21.

### Services at cutover
- `echo-core.service` — active (running), uses echo-core/.venv + echo-core paths
- `echo-taskboard.service` — active (running), new unit at `~/.config/systemd/user/echo-taskboard.service`, WorkingDirectory=`/home/moltbot/echo-core/dashboard`, ExecStart=`.venv/bin/python3 api.py`
- `echo-whatsapp-bridge.service` — active (running), unchanged
- `openclaw-gateway.service` — **inactive + disabled**, credentials stripped

### Credentials stripped from `~/.openclaw/`
- `credentials/` dir (Discord + Telegram + WhatsApp pairing) — deleted
- `identity/` dir (device auth) — deleted
- `devices/` dir (paired devices) — deleted
- `agents/*/agent/auth-profiles.json` (20 files) — deleted
- `agents/*/sessions/sessions.json` (20 files) — deleted
- **Preserved:** `cron/jobs.json` (+bak) as audit artifact; `openclaw.json` (main config, no known secrets); npm `lib/` (harmless).

### What's enabled after migration
- **Shell jobs (5):** `anaf-monitor`, `security-audit-daily`, `kb-index-refresh`, `archive-tasks-daily`, `backup-config` — all enabled
- **Claude jobs enabled (2):** `newsletter-test`, `heartbeat-2h`
- **Claude jobs disabled (13):** morning-report, evening-report, morning-coaching, evening-coaching, weekly-planning-sun, content-discovery, provocare-reminder, exercise-snack-1/2/3, grup-sprijin-5feb, grup-sprijin-pregatire — ready to enable after Marius reviews each

### Crontab
- `0 2 * * * /home/moltbot/echo-core/tools/backup_config.sh` (was clawd)
- `10 14 * * 4,5,1 ... check_newsletter_cercetasi.py` (unchanged)
- `0 9 21 5 * ...` — **May 21 2026 cleanup reminder** (writes to `$HOME/REMINDER-openclaw-cleanup.txt` and appends to `logs/migration-reminder.log`)

### Verification PASS
- ANAF `status.json.anaf.lastCheck` moved from **03 Apr 2026, 22:07** → **21 Apr 2026, 10:04** with 3 real changes detected on first manual trigger.
- `GSTACK-CRON: changes=3` marker emitted correctly; scheduler↔anaf contract verified.
- `/api/cron` returns 7 jobs (enabled shell + claude).
- `/api/agents` and `/api/activity` return 404 (removed as planned).
- Dashboard /api/status OK.

---

---

## Pre-flight (read-only)

1. Confirm clean git state on echo-core master:
   ```
   cd /home/moltbot/echo-core && git status
   ```

2. Verify tests pass:
   ```
   cd /home/moltbot/echo-core
   source .venv/bin/activate && pytest tests/ -x
   ```

3. Backup:
   ```
   cp -rp /home/moltbot/clawd/dashboard /home/moltbot/clawd-backup-$(date +%Y-%m-%d)/
   cp -rp /home/moltbot/clawd/memory   /home/moltbot/clawd-backup-$(date +%Y-%m-%d)/memory
   ```

## Legacy consumer grep (decide on compat symlink)

4. Check whether anything still reads clawd/memory:
   ```
   grep -rn 'clawd/memory' /home/moltbot/{bin,.config,.openclaw} 2>/dev/null
   grep -rn 'clawd/memory' /home/moltbot/echo-core 2>/dev/null
   ```
   - If empty → skip **step 11** (no compat symlink needed).
   - If non-empty → keep **step 11**.

## Stop services

5. ```
   systemctl --user stop echo-core echo-taskboard echo-whatsapp-bridge openclaw-gateway
   ```

## Copy ANAF live state

6. ```
   cp -rp /home/moltbot/clawd/tools/anaf-monitor/{hashes.json,versions.json,monitor.log} \
          /home/moltbot/echo-core/tools/anaf-monitor/ 2>/dev/null
   cp -rp /home/moltbot/clawd/tools/anaf-monitor/snapshots \
          /home/moltbot/echo-core/tools/anaf-monitor/
   diff -r /home/moltbot/clawd/tools/anaf-monitor/snapshots \
           /home/moltbot/echo-core/tools/anaf-monitor/snapshots
   ```
   Diff should be empty (or only show new snapshots echo-core captured during testing).

## Dashboard migration

7. Delete echo-core dashboard placeholder content if any collisions, then:
   ```
   cp -rp /home/moltbot/clawd/dashboard/{habits,issues,status,todos}.json \
          /home/moltbot/echo-core/dashboard/
   cp -rp /home/moltbot/clawd/dashboard/tests/ \
          /home/moltbot/echo-core/dashboard/tests/
   # Recreate the 4 dashboard symlinks pointing into echo-core:
   ln -sfn /home/moltbot/echo-core/memory           /home/moltbot/echo-core/dashboard/memory
   ln -sfn /home/moltbot/echo-core/conversations    /home/moltbot/echo-core/dashboard/conversations   # create conversations/ first if you want this
   ln -sfn /home/moltbot/echo-core/memory/kb        /home/moltbot/echo-core/dashboard/notes-data
   ln -sfn /home/moltbot/echo-core/memory/kb/youtube /home/moltbot/echo-core/dashboard/youtube-notes
   ```

## Memory inversion

8. `rm /home/moltbot/echo-core/memory`  *(removes symlink only, not target)*
9. `cp -rp /home/moltbot/clawd/memory /home/moltbot/echo-core/memory`
10. `diff -rq /home/moltbot/clawd/memory /home/moltbot/echo-core/memory` *(verify identical)*
11. *(only if step 4 found consumers)*
    ```
    mv /home/moltbot/clawd/memory /home/moltbot/clawd/memory.old-2026-04
    ln -s /home/moltbot/echo-core/memory /home/moltbot/clawd/memory
    ```
12. `rm -rf /home/moltbot/echo-core/memory.bak` *(leftover, safe to delete)*

## Systemd

13. Copy the template into place:
    ```
    cp /home/moltbot/echo-core/dashboard/echo-taskboard.service \
       /home/moltbot/.config/systemd/user/echo-taskboard.service
    systemctl --user daemon-reload
    ```

## Crontab

14. ```
    bash /home/moltbot/echo-core/scripts/update_crontab.sh
    ```

## Decommission OpenClaw

15. `systemctl --user stop openclaw-gateway`
16. `systemctl --user disable openclaw-gateway`
17. Strip credentials from `~/.openclaw/` but keep `jobs.json.bak`:
    ```
    cd /home/moltbot/.openclaw
    find . -name 'auth*' -o -name '*token*' -o -name '*.secret' | xargs rm -v 2>/dev/null
    ls -la agents/*/   # inspect for any remaining secrets, delete manually
    ```
18. **Note:** schedule a reminder for 2026-05-21 to `rm -rf /home/moltbot/.openclaw`
    entirely if nothing was restored.

## Restart

19. `systemctl --user start echo-core echo-taskboard echo-whatsapp-bridge`
20. `systemctl --user status echo-core echo-taskboard echo-whatsapp-bridge` — all **active (running)**.
21. `systemctl --user status openclaw-gateway` — **inactive (dead)**.

## Verification

22. `curl -s http://localhost:8088/api/status` → `{"status":"ok",...}`
23. Visit `https://moltbot.tailf7372d.ts.net/echo/` — home page loads.
24. `/api/cron` panel populated with echo-core jobs (anaf-monitor, morning-report, etc).
25. `/api/agents` returns 404 (removed).
26. Click **Commit** in `index.html` — creates commit on echo-core repo.
27. Manually trigger anaf monitor:
    ```
    cd /home/moltbot/echo-core && .venv/bin/python3 tools/anaf-monitor/monitor_v2.py
    ```
    Verify `status.json` updates **and** stdout ends with
    `GSTACK-CRON: changes=N`.
28. Wait for first scheduled anaf-monitor trigger (10:00 or 16:00 Mon-Fri).
    Check `echo-core.log` for execution.

---

## Rollback path (if anything breaks badly)

**Concrete values for this migration (executed 2026-04-21):**

```
# Stop current services
systemctl --user stop echo-core echo-taskboard echo-whatsapp-bridge

# Restore memory directory
rm -rf /home/moltbot/echo-core/memory
cp -rp /home/moltbot/clawd-backup-2026-04-21/memory /home/moltbot/clawd/memory
ln -s /home/moltbot/clawd/memory /home/moltbot/echo-core/memory

# Restore dashboard source (symlinks will come back with it)
cp -rp /home/moltbot/clawd-backup-2026-04-21/dashboard /home/moltbot/clawd/dashboard

# Restore old systemd unit (paths back to clawd/dashboard + /usr/bin/python3)
cat > ~/.config/systemd/user/echo-taskboard.service <<'EOF'
[Unit]
Description=Echo Task Board API
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/moltbot/clawd/dashboard
ExecStart=/usr/bin/python3 /home/moltbot/clawd/dashboard/api.py
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
EOF

# Revert git to pre-migration state
git -C /home/moltbot/echo-core reset --hard 4e78ef7

# Restore crontab backup_config line (sed in reverse)
crontab -l | sed -E 's#/home/moltbot/echo-core/tools/backup_config\.sh#/home/moltbot/clawd/tools/backup_config.sh#g' | crontab -

# Re-enable openclaw (credentials are GONE — you'll need to re-pair Discord/Telegram/WhatsApp)
systemctl --user enable openclaw-gateway
systemctl --user daemon-reload

# Restart everything
systemctl --user start echo-core echo-taskboard echo-whatsapp-bridge openclaw-gateway
```

**Note:** After rollback, OpenClaw credentials are gone (stripped during migration). Re-pairing requires going through OpenClaw's pairing flows for Discord/Telegram/WhatsApp. If you want clean rollback without losing pairing, do the rollback within the 30-day window **before** running the May 21 cleanup reminder.

---

## Notes

- **Cron schedules are Bucharest local time**, not UTC.
- **Most imported claude jobs arrive DISABLED** — enable them via `eco` / dashboard
  once you've verified each one produces the expected output.
- `heartbeat-2h` is the **only imported claude job that stays enabled** (preserving
  its state from OpenClaw).
- The 5 shell jobs (anaf-monitor, security-audit-daily, kb-index-refresh,
  archive-tasks-daily, backup-config) start **enabled** on day one.
