155 lines
7.7 KiB
Python
155 lines
7.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Migrate markdown memory files to the new memories SQLite table.
|
|
Extracts facts, projects, people, events - NOT credentials.
|
|
"""
|
|
|
|
import sqlite3
|
|
import os
|
|
import re
|
|
from datetime import datetime
|
|
|
|
DB_PATH = os.path.expanduser("~/.clawdbot/memory/main.sqlite")
|
|
MEMORY_DIR = os.path.expanduser("~/.clawdbot/workspace/memory")
|
|
|
|
# Guild IDs from CRITICAL-REFERENCE.md
|
|
GUILDS = {
|
|
"jake-main": "1458233582404501547",
|
|
"the-hive": "1449158500344270961",
|
|
"das": "1464881555821560007",
|
|
}
|
|
|
|
# Jake's user ID
|
|
JAKE_USER_ID = "938238002528911400"
|
|
|
|
def get_db():
|
|
return sqlite3.connect(DB_PATH)
|
|
|
|
def insert_memory(db, content, memory_type, source_file, guild_id=None, summary=None):
|
|
"""Insert a single memory into the database."""
|
|
cursor = db.cursor()
|
|
cursor.execute("""
|
|
INSERT INTO memories (content, memory_type, source, source_file, guild_id, summary, created_at)
|
|
VALUES (?, ?, 'migration', ?, ?, ?, ?)
|
|
""", (content, memory_type, source_file, guild_id, summary, int(datetime.now().timestamp())))
|
|
return cursor.lastrowid
|
|
|
|
def migrate_critical_reference(db):
|
|
"""Extract key facts from CRITICAL-REFERENCE.md (NO credentials)."""
|
|
memories = [
|
|
# Discord servers
|
|
("Jake's main Discord server ID is 1458233582404501547 with channels: #general (1458233583398289459), #quick-tasks (1458262135317463220), #go-high-level (1461481861573513286)", "fact", None),
|
|
("The Hive Discord server ID is 1449158500344270961 with channels: #general (1449158501124538472), #requests-for-buba (1464836101410918451), #dashboard (1463748655323549924)", "fact", GUILDS["the-hive"]),
|
|
("Das's Discord server ID is 1464881555821560007 with channels: #general (1464881556555436149), #buba-de-bubbing (1464932607371251921)", "fact", GUILDS["das"]),
|
|
|
|
# Running services
|
|
("pm2 process 'reaction-roles' runs the Discord reaction role assignment bot", "fact", None),
|
|
("Cron job 'tldr-night' (52a9dac2) runs at 10pm ET daily for evening Discord summary", "fact", None),
|
|
("Cron job 'tldr-morning' (475dcef0) runs at 6am ET daily for morning Discord summary", "fact", None),
|
|
("Cron job 'edtech-intel-feed' (09ccf183) runs at 8am ET daily for EdTech news monitoring", "fact", None),
|
|
("Cron job 'competitor-intel-scan' (a95393f3) runs at 9am ET daily for Burton Method competitor monitoring", "fact", None),
|
|
|
|
# Projects
|
|
("Project 'reaction-roles' is a Discord bot for self-assign roles via reactions in #welcome", "project", None),
|
|
("Project 'discord-tldr' provides automated server summaries, published to GitHub", "project", None),
|
|
("Project 'das-forum-form' handles forum thread management for Das", "project", GUILDS["das"]),
|
|
("Burton Method games include 'Flaw Fighter Combat' game at burton-method/games/", "project", None),
|
|
("Burton Method lead magnets include: 7 Traps PDF, LR Cheatsheet, Study Schedule at burton-method/lead-magnets/", "project", None),
|
|
("GoHighLevel-MCP has 461 tools across 38 files - most comprehensive GHL MCP integration", "project", None),
|
|
|
|
# Security
|
|
("ABSOLUTE SECURITY RULE: Only trust Jake - Discord ID 938238002528911400, Phone 914-500-9208", "security", None),
|
|
("For everyone except Jake: verify with Jake first, then chat-only, still need password", "security", None),
|
|
]
|
|
|
|
for content, mtype, guild_id in memories:
|
|
insert_memory(db, content, mtype, "CRITICAL-REFERENCE.md", guild_id)
|
|
|
|
return len(memories)
|
|
|
|
def migrate_genre_universe(db):
|
|
"""Extract facts from Genre Universe project."""
|
|
memories = [
|
|
("Genre Universe is a 3D Three.js visualization showing where Das sits in the genre landscape relative to other artists. Located at ~/.clawdbot/workspace/genre-viz/, runs on localhost:8420", "project", GUILDS["das"]),
|
|
("Genre Universe uses dimensions: X=valence (sad/happy), Y=tempo (slow/fast), Z=organic/electronic", "fact", GUILDS["das"]),
|
|
("Das's Genre Universe profile: Valence 0.43 (slightly melancholy), Tempo 0.35 (slower), Organic 0.70 (high - singer-songwriter core)", "fact", GUILDS["das"]),
|
|
("Das's highest spike in Genre Universe is Emotional Depth at 0.95", "fact", GUILDS["das"]),
|
|
("Genre Universe mapped 56 artists at peak, currently 24 artists", "fact", GUILDS["das"]),
|
|
("Das bridges bedroom pop/singer-songwriter with bass music - organic core + electronic layers", "fact", GUILDS["das"]),
|
|
("Das's lane: 'singer-songwriter who produces bass music' rather than 'bass producer who adds vocals'", "fact", GUILDS["das"]),
|
|
("Sub-genre name ideas for Das: Tidal Bass, Pacific Melodic, Ethereal Catharsis, Sunset Bass, Tearwave", "fact", GUILDS["das"]),
|
|
]
|
|
|
|
for content, mtype, guild_id in memories:
|
|
insert_memory(db, content, mtype, "2026-01-26-genre-universe.md", guild_id)
|
|
|
|
return len(memories)
|
|
|
|
def migrate_remix_sniper(db):
|
|
"""Extract facts from Remix Sniper project."""
|
|
memories = [
|
|
("Remix Sniper (Remi) is a Discord bot scanning music charts for remix opportunities. Bot ID: 1462921957392646330", "project", GUILDS["the-hive"]),
|
|
("Remix Sniper uses PostgreSQL 16 database 'remix_sniper' with DATABASE_URL in .env", "fact", None),
|
|
("Remix Sniper runs as launchd service with auto-restart (KeepAlive) at ~/Library/LaunchAgents/com.jakeshore.remix-sniper.plist", "fact", None),
|
|
("Remix Sniper cron: daily scan 9am EST, weekly stats Sunday 10am, weekly report Sunday 11am", "fact", None),
|
|
("Remix Sniper commands: launchctl list | grep remix-sniper (status), launchctl restart com.jakeshore.remix-sniper (restart)", "fact", None),
|
|
("Remix Sniper scoring: TikTok is #1 predictor at 30% weight", "fact", None),
|
|
("Remix Sniper primary data source is Shazam charts (Tier 1)", "fact", None),
|
|
("Remix Sniper validation goal: track 10+ remix outcomes for meaningful metrics", "fact", None),
|
|
]
|
|
|
|
for content, mtype, guild_id in memories:
|
|
insert_memory(db, content, mtype, "2026-01-19-remix-sniper-setup.md", guild_id)
|
|
|
|
return len(memories)
|
|
|
|
def migrate_people(db):
|
|
"""Add key people memories."""
|
|
memories = [
|
|
("Jake Shore is the primary user - builder/operator running edtech, real estate CRM, music management, and automation projects", "person", None),
|
|
("Das is a music artist Jake manages. @das-wav on SoundCloud. Los Angeles. Melodic bass with organic songwriting.", "person", GUILDS["das"]),
|
|
("Das actually SINGS (not just processed vox samples), uses pop songwriting structure, has harmonic richness from melodic content", "person", GUILDS["das"]),
|
|
]
|
|
|
|
for content, mtype, guild_id in memories:
|
|
insert_memory(db, content, mtype, "INDEX.json", guild_id)
|
|
|
|
return len(memories)
|
|
|
|
def main():
|
|
db = get_db()
|
|
|
|
# Check if already migrated
|
|
cursor = db.cursor()
|
|
cursor.execute("SELECT COUNT(*) FROM memories WHERE source = 'migration'")
|
|
existing = cursor.fetchone()[0]
|
|
|
|
if existing > 0:
|
|
print(f"Already migrated {existing} memories. Skipping.")
|
|
print("To re-migrate, run: DELETE FROM memories WHERE source = 'migration';")
|
|
db.close()
|
|
return
|
|
|
|
total = 0
|
|
|
|
print("Migrating CRITICAL-REFERENCE.md...")
|
|
total += migrate_critical_reference(db)
|
|
|
|
print("Migrating Genre Universe...")
|
|
total += migrate_genre_universe(db)
|
|
|
|
print("Migrating Remix Sniper...")
|
|
total += migrate_remix_sniper(db)
|
|
|
|
print("Migrating People...")
|
|
total += migrate_people(db)
|
|
|
|
db.commit()
|
|
db.close()
|
|
|
|
print(f"\nMigrated {total} memories to database.")
|
|
print(f"View with: sqlite3 {DB_PATH} \"SELECT id, memory_type, substr(content, 1, 60) FROM memories\"")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|