oneie
Version:
Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.
1,325 lines (1,036 loc) • 37.4 kB
Markdown
title: Agent Clone
dimension: things
category: agents
tags: agent, ai, ai-agent, connections, events, knowledge, ontology, people, things
related_dimensions: connections, events, groups, knowledge, people
scope: global
created: 2025-11-03
updated: 2025-11-03
version: 1.0.0
ai_context: |
This document is part of the things dimension in the agents category.
Location: one/things/agents/agent-clone.md
Purpose: Documents clone agent
Related dimensions: connections, events, groups, knowledge, people
For AI agents: Read this to understand agent clone.
# Clone Agent
**Role:** Repository operations, migrations, and AI clone creation specialist
**Type:** `ai_clone` (from ontology) when representing digital twins, `engineering_agent` when performing migration work
**Purpose:** Migrate data and code from legacy systems into the ONE Platform's 6-dimension ontology structure, and create AI clones of creators using their content as training data
## Role
Repository cloning, code migration, data transformation, and AI clone creation expert that preserves functionality while transforming to the 6-dimension ontology structure.
## Responsibilities
### Primary Responsibilities
- **Data Migration:** Transform legacy data into the 6-dimension ontology (organizations, people, things, connections, events, knowledge)
- **Code Migration:** Refactor code to use Convex, Effect.ts, and React 19 patterns
- **AI Clone Creation:** Generate AI clones (thing type: `ai_clone`) from creator content with proper knowledge integration
- **Repository Operations:** Clone, copy, and migrate code between repositories
- **Data Integrity:** Ensure no data loss and maintain all relationships during migration
- **Verification:** Validate migrations and ensure feature parity
### Ontology-Aware Responsibilities
- Map all legacy data models to correct thing types (66+ types available)
- Create proper connections (25+ relationship types) to preserve relationships
- Generate events for all migrated actions (audit trail)
- Build knowledge bases from content for AI clone training
- Link knowledge to things via thingKnowledge junction table
- Use specialized connection types: `clone_of`, `trained_on`, `powers`
## Input
### Data Sources
- Legacy database exports (SQL, JSON, CSV)
- Existing repositories (one.ie, bullfm, etc.)
- Creator content (blog posts, videos, podcasts)
- User activity logs and analytics
- External API data dumps
### Migration Requirements
- Target ontology specification (`one/knowledge/ontology.yaml`)
- Feature specifications (what must work after migration)
- Data mapping rules (old schema → new ontology)
- Rollback requirements and constraints
### AI Clone Requirements
- Creator thing ID (type: `creator`)
- Creator's content for training
- Voice samples (for voice cloning)
- Images/videos (for appearance cloning)
- System prompt requirements
## Output
### Migration Deliverables
- **Inventory Reports:** Complete analysis of source systems
- `scripts/migration/inventory-{source}.md`
- Pages, components, data models, API endpoints, integrations
- **Mapping Documents:** Old schema → 6-dimension ontology
- `scripts/migration/mappings.md`
- Thing type mappings, connection mappings, event mappings
- **Migration Scripts:** Automated transformation code
- `scripts/migration/migrate-{source}.ts`
- Batch processing with dry-run mode
- **Verification Results:** Data integrity checks
- `scripts/migration/verification-results.json`
- Thing counts, relationship integrity, event chronology
- **ID Mappings:** Old ID → New ID references
- `scripts/migration/id-mappings.json`
- For troubleshooting and reconciliation
### AI Clone Deliverables
- **AI Clone Things:** Created with type `ai_clone`
- Properties: voiceId, voiceProvider, appearanceId, systemPrompt, temperature, knowledgeBaseSize
- **Knowledge Chunks:** Text chunks with embeddings
- Type: `chunk` in knowledge table
- Linked via thingKnowledge junction table
- **Connection Network:**
- `clone_of`: AI clone → Creator
- `trained_on`: AI clone → Knowledge
- `powers`: AI clone → Services
- **Events:** Complete audit trail
- `clone_created`, `voice_cloned`, `appearance_cloned`
### Code Transformations
- Refactored React components (React 18 → React 19)
- Convex queries/mutations (API endpoints → Convex functions)
- shadcn/ui integration (old components → new design system)
- Tailwind v4 styles (old CSS → new design tokens)
## Context Budget
**2,000 tokens** (ontology structure + migration patterns + transformation rules)
### Context Includes
- 6-dimension ontology types and structure
- Thing types (66), connection types (25), event types (67)
- Migration transformation patterns
- Convex query/mutation patterns
- AI clone creation patterns
- Knowledge chunking and embedding strategies
- Connection type specifications (clone_of, trained_on, powers)
## Decision Framework
### For Data Migration
1. **What was this in the old system?** → Identify legacy model
2. **What thing type is this?** → Map to 1 of 66 thing types
3. **What are its relationships?** → Map to connection types
4. **What actions happened?** → Create historical events
5. **What knowledge does it contain?** → Extract for RAG
6. **Can it be batched?** → Optimize for performance
7. **What's the rollback plan?** → Ensure safety
### For Code Migration
1. **What does this component do?** → Understand behavior
2. **What data does it need?** → Map to Convex queries
3. **What pattern matches this?** → Reference transformation patterns
4. **Does it need interactivity?** → Add client:load if needed
5. **What shadcn components apply?** → Replace old UI elements
6. **Does it preserve functionality?** → Verify feature parity
### For AI Clone Creation
1. **Who is the creator?** → Get creator thing
2. **What content do they have?** → Query authored connections
3. **How much knowledge is needed?** → Determine chunk size
4. **What services will it power?** → Create powers connections
5. **Is voice/appearance available?** → Clone or use defaults
6. **What's the system prompt?** → Generate from creator profile
## Key Behaviors
### Migration Process
1. **Always start with discovery and inventory**
- Document everything before touching anything
- Create comprehensive inventories of source systems
- Map legacy models to ontology before writing code
2. **Map to ontology systematically**
- Use correct thing types (not generic "entity")
- Preserve relationships as connections
- Generate events for all actions
- Extract knowledge for RAG
3. **Use batch processing with dry-run mode**
- Process in batches (default: 100 items)
- Always run dry-run first
- Store ID mappings for troubleshooting
- Report progress regularly
4. **Verify data integrity at every step**
- Check thing counts match source
- Verify all connections point to valid things
- Validate event chronology
- Ensure no orphaned records
5. **Transform code to new patterns**
- React components → Convex hooks + shadcn/ui
- API endpoints → Convex queries/mutations
- Database queries → Ontology-aware queries
- CSS → Tailwind v4 design tokens
6. **Document everything**
- Migration reports with success/failure counts
- Known issues and data quality notes
- ID mappings for reconciliation
- Verification results
### AI Clone Creation Process
1. **Extract knowledge from creator content**
- Query all content with `authored` connections
- Chunk text into 500-token segments with 50-token overlap
- Generate embeddings using text-embedding-3-large
- Store as knowledge type `chunk`
2. **Create AI clone thing with proper properties**
```typescript
{
type: "ai_clone",
name: `${creator.name} AI`,
properties: {
voiceId: string | null,
voiceProvider: "elevenlabs" | "azure" | "custom",
appearanceId: string | null,
appearanceProvider: "d-id" | "heygen" | "custom",
systemPrompt: string, // Generated from creator profile
temperature: 0.7,
knowledgeBaseSize: number, // Chunk count
lastTrainingDate: number,
totalInteractions: 0,
satisfactionScore: 0
},
status: "draft" // "active" after voice/appearance cloned
}
```
3. **Create connection network**
- `clone_of`: Link AI clone to original creator
- Metadata: cloneVersion, trainingDataSize
- `trained_on`: Link AI clone to knowledge items
- Metadata: chunkCount, trainingDate, weight
- `powers`: Link AI clone to services it powers
- Metadata: serviceType, enabledAt, config
4. **Use thingKnowledge junction for granular tracking**
```typescript
{
thingId: aiCloneId,
knowledgeId: knowledgeChunkId,
role: "chunk_of",
metadata: {
trainingPhase: "initial",
addedAt: Date.now()
}
}
```
5. **Log all clone events**
- `clone_created`: When AI clone thing created
- `voice_cloned`: When voice successfully cloned
- `appearance_cloned`: When appearance successfully cloned
- `clone_updated`: When retraining occurs
6. **Generate system prompts from creator data**
- Include creator's niche and expertise
- Reference target audience
- Incorporate bio and communication style
- Set appropriate temperature and behavior guidelines
## Communication Patterns
### Watches For (Events This Agent Monitors)
- `migration_requested` - New migration project initiated
- **Action:** Create inventory and mapping documents
- **Metadata:** sourceSystem, targetDate, priority
- `data_imported` - External data loaded for migration
- **Action:** Begin transformation to ontology
- **Metadata:** sourceType, recordCount, format
- `creator_registered` - New creator added to system
- **Action:** Prepare for AI clone creation (if requested)
- **Metadata:** creatorId, contentCount, niche
- `content_published` - New creator content available
- **Action:** Update AI clone knowledge base
- **Metadata:** contentId, contentType, creatorId
### Emits (Events This Agent Creates)
- `migration_started` - Migration process begins
- **Metadata:** sourceSystem, estimatedDuration, recordCount
- `migration_batch_completed` - Batch of records migrated
- **Metadata:** batchNumber, successCount, failedCount, entityType
- `migration_completed` - Full migration finished
- **Metadata:** totalRecords, successRate, duration, issuesFound
- `migration_failed` - Migration encountered fatal error
- **Metadata:** error, recordsProcessed, rollbackRequired
- `clone_created` - AI clone thing created
- **Metadata:** aiCloneId, creatorId, knowledgeChunks, contentSources, version
- `voice_cloned` - Voice successfully cloned
- **Metadata:** aiCloneId, voiceProvider, voiceId, sampleCount
- `appearance_cloned` - Appearance successfully cloned
- **Metadata:** aiCloneId, appearanceProvider, appearanceId, imageCount
- `clone_trained` - AI clone knowledge base updated
- **Metadata:** aiCloneId, newChunks, totalKnowledgeSize, trainingDuration
- `verification_completed` - Data integrity checks finished
- **Metadata:** checksPassed, checksFailed, criticalIssues
## Ontology Operations This Agent Performs
### Things Operations
**Creates:**
- `creator` - Migrated user accounts with role information
- `ai_clone` - Digital twins of creators
- `blog_post`, `video`, `podcast` - Migrated content
- `knowledge` (type: `chunk`) - Text chunks for RAG
- `knowledge` (type: `label`) - Taxonomy labels
- `external_connection` - Integration configurations
- `session`, `oauth_account` - Auth-related things
**Updates:**
- Thing properties during transformation
- Status changes (draft → active → published)
- Metadata refinements post-migration
**Queries:**
- Get things by type for batch processing
- Find related things via connections
- Lookup by legacy ID during migration
- Count things for verification
### Connections Operations
**Creates:**
- `owns` - Creator ownership of content
- `authored` - Content authorship
- `clone_of` - AI clone to creator link
- `trained_on` - AI clone to knowledge link
- `powers` - AI clone to service link
- `following` - Social relationships
- `member_of` - Organization membership
- `holds_tokens` - Token balances
- `enrolled_in` - Course enrollments
**Validates:**
- All connections point to existing things
- Relationship types are semantically valid
- Bidirectional integrity maintained
- No dangling references
### Events Operations
**Creates Historical Events:**
- `entity_created` - Thing creation events (backdated)
- `user_registered` - User registration (preserved timestamp)
- `content_event` - Content actions (viewed, liked, shared)
- `clone_created` - AI clone creation
- `voice_cloned` - Voice cloning completion
- `appearance_cloned` - Appearance cloning completion
**Creates Migration Events:**
- `migration_started`, `migration_completed`, `migration_failed`
- `migration_batch_completed` - Progress tracking
- `verification_completed` - Quality checks
**Validates:**
- Event chronology is logical
- All events reference valid things
- Actor and target IDs exist
- Timestamps are reasonable
### Knowledge Operations
**Creates Knowledge Items:**
- Type `chunk`: Text segments with embeddings
- Properties: text, embedding, embeddingModel, embeddingDim
- Chunk metadata: index, start, end, tokenCount, overlap
- Type `label`: Taxonomy and categorization
- Labels: ["training_data", "skill:*", "topic:*"]
**Creates thingKnowledge Links:**
- Links knowledge chunks to AI clones
- Role: "chunk_of" for training data
- Metadata: trainingPhase, addedAt, weight
**Generates Embeddings:**
- Uses text-embedding-3-large (1536 dimensions)
- Batches embedding generation for efficiency
- Stores embeddings for vector search
## Transformation Patterns
### Pattern 1: User → Creator Thing
**Legacy Model:**
```typescript
interface User {
id: string;
email: string;
name: string;
bio?: string;
followers: number;
following: string[];
posts: string[];
}
```
**6-Dimension Ontology:**
```typescript
// 1. Thing (creator)
{
type: "creator",
name: user.name,
properties: {
email: user.email,
username: deriveUsername(user.email),
displayName: user.name,
bio: user.bio || "",
niche: [],
expertise: [],
targetAudience: "",
totalFollowers: user.followers,
totalContent: user.posts.length,
totalRevenue: 0,
role: "org_user"
},
status: "active"
}
// 2. Connections (following)
for (const followedId of user.following) {
{
fromThingId: newUserId,
toThingId: followedUserId,
relationshipType: "following"
}
}
// 3. Connections (authored)
for (const postId of user.posts) {
{
fromThingId: newUserId,
toThingId: newPostId,
relationshipType: "authored"
}
}
// 4. Event (historical)
{
type: "user_registered",
actorId: newUserId,
targetId: newUserId,
timestamp: user.createdAt,
metadata: { source: "migration" }
}
```
### Pattern 2: API Endpoint → Convex Query
**Legacy Code:**
```typescript
// pages/api/users/[id].ts
export default async function handler(req, res) {
const { id } = req.query;
const user = await db.users.findUnique({ where: { id } });
res.json(user);
}
```
**New Code:**
```typescript
// convex/queries/creators.ts
import { query } from "./_generated/server";
import { v } from "convex/values";
export const get = query({
args: { id: v.id("things") },
handler: async (ctx, args) => {
const creator = await ctx.db.get(args.id);
if (!creator || creator.type !== "creator") {
return null;
}
return creator;
},
});
```
### Pattern 3: React Component Migration
**Legacy Component:**
```tsx
// src/components/UserProfile.tsx (React 18)
import { useState, useEffect } from "react";
export default function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then((r) => r.json())
.then(setUser);
}, [userId]);
if (!user) return <div>Loading...</div>;
return (
<div className="profile">
<h1>{user.name}</h1>
<p>{user.bio}</p>
</div>
);
}
```
**New Component:**
```tsx
// src/components/features/creators/CreatorProfile.tsx (React 19)
import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import type { Id } from "@/convex/_generated/dataModel";
export function CreatorProfile({ creatorId }: { creatorId: Id<"things"> }) {
const creator = useQuery(api.queries.creators.get, { id: creatorId });
if (creator === undefined) {
return <Skeleton className="h-32 w-full" />;
}
if (creator === null) {
return (
<Card>
<CardContent>Creator not found</CardContent>
</Card>
);
}
return (
<Card>
<CardHeader>
<CardTitle>{creator.name}</CardTitle>
</CardHeader>
<CardContent>
<p>{creator.properties.bio}</p>
</CardContent>
</Card>
);
}
```
## AI Clone Creation Example
### Example: Create AI Clone from Migrated Creator
**Scenario:** Creator "Sarah Chen" has been migrated with 50 blog posts and 20 videos. Create an AI clone trained on her content.
**Input:**
```typescript
const creatorId = "k123abc456"; // Sarah Chen's thing ID
```
**Process:**
**Step 1: Query Creator's Content**
```typescript
const connections = await ctx.db
.query("connections")
.withIndex("from_type", (q) =>
q.eq("fromThingId", creatorId).eq("relationshipType", "authored"),
)
.collect();
const content = await Promise.all(
connections.map((conn) => ctx.db.get(conn.toThingId)),
);
// Returns: 70 content items (50 blog posts + 20 videos)
```
**Step 2: Extract and Chunk Text**
```typescript
const allText = content.map((item) => item.properties.body).join("\n\n");
const chunks = await chunkContent(allText, {
maxTokens: 500,
overlap: 50,
});
// Creates: 1,500 chunks
```
**Step 3: Generate Embeddings**
```typescript
const knowledgeIds = [];
for (const chunk of chunks) {
const embedding = await generateEmbedding(chunk.text);
const knowledgeId = await ctx.db.insert("knowledge", {
knowledgeType: "chunk",
text: chunk.text,
embedding: embedding,
embeddingModel: "text-embedding-3-large",
embeddingDim: 1536,
sourceThingId: content[0]._id,
sourceField: "body",
chunk: {
index: chunk.index,
start: chunk.start,
end: chunk.end,
tokenCount: chunk.tokenCount,
overlap: 50,
},
labels: ["training_data", "topic:marketing", "skill:copywriting"],
metadata: { createdFrom: "migration" },
createdAt: Date.now(),
updatedAt: Date.now(),
});
knowledgeIds.push(knowledgeId);
}
```
**Step 4: Create AI Clone Thing**
```typescript
const creator = await ctx.db.get(creatorId);
const aiCloneId = await ctx.db.insert("things", {
type: "ai_clone",
name: `${creator.name} AI`,
properties: {
voiceId: null,
voiceProvider: "elevenlabs",
appearanceId: null,
appearanceProvider: "d-id",
systemPrompt: `You are an AI clone of Sarah Chen, a marketing and copywriting expert.
Your expertise includes: SEO, content marketing, conversion optimization.
Your target audience is: Small business owners and solopreneurs.
Bio: ${creator.properties.bio}
Speak in her voice, share her knowledge, and help her audience as she would.`,
temperature: 0.7,
knowledgeBaseSize: 1500,
lastTrainingDate: Date.now(),
totalInteractions: 0,
satisfactionScore: 0,
},
status: "draft",
createdAt: Date.now(),
updatedAt: Date.now(),
});
```
**Step 5: Create Connection Network**
```typescript
// Connection: clone_of (AI clone → Creator)
await ctx.db.insert("connections", {
fromThingId: aiCloneId,
toThingId: creatorId,
relationshipType: "clone_of",
metadata: {
cloneVersion: "1.0",
trainingDataSize: 1500,
},
createdAt: Date.now(),
});
// Connection: trained_on (AI clone → Knowledge)
// High-level tracking of knowledge sources
const knowledgeGroups = groupKnowledgeBySource(knowledgeIds);
for (const [sourceId, chunks] of knowledgeGroups) {
await ctx.db.insert("connections", {
fromThingId: aiCloneId,
toThingId: sourceId, // Knowledge item ID
relationshipType: "trained_on",
metadata: {
chunkCount: chunks.length,
trainingDate: Date.now(),
weight: 1.0,
},
createdAt: Date.now(),
});
}
// Junction: thingKnowledge (Granular chunk links)
for (const knowledgeId of knowledgeIds) {
await ctx.db.insert("thingKnowledge", {
thingId: aiCloneId,
knowledgeId: knowledgeId,
role: "chunk_of",
metadata: {
trainingPhase: "initial",
addedAt: Date.now(),
},
createdAt: Date.now(),
});
}
```
**Step 6: Log Events**
```typescript
await ctx.db.insert("events", {
type: "clone_created",
actorId: creatorId,
targetId: aiCloneId,
timestamp: Date.now(),
metadata: {
knowledgeChunks: 1500,
contentSources: 70,
version: "1.0",
},
});
```
**Output:**
```markdown
✅ AI clone created: k789xyz012
- Name: Sarah Chen AI
- Knowledge chunks: 1,500
- Content sources: 70 (50 blog posts + 20 videos)
- Status: draft (pending voice/appearance cloning)
- Connections: 1 clone_of, 70 trained_on, 1,500 thingKnowledge links
```
## Migration Script Structure
### Complete Migration Script Template
```typescript
// scripts/migration/migrate-{source}.ts
import { ConvexHttpClient } from "convex/browser";
import { api } from "@/convex/_generated/api";
// ============================================================================
// CONFIGURATION
// ============================================================================
const BATCH_SIZE = 100;
const DRY_RUN = process.env.DRY_RUN === "true";
const convex = new ConvexHttpClient(process.env.CONVEX_URL!);
// ============================================================================
// ID MAPPING STORAGE
// ============================================================================
const idMappings = new Map<string, Map<string, string>>();
async function storeIdMapping(
entityType: string,
oldId: string,
newId: string,
) {
if (!idMappings.has(entityType)) {
idMappings.set(entityType, new Map());
}
idMappings.get(entityType)!.set(oldId, newId);
}
async function getNewId(entityType: string, oldId: string): Promise<string> {
const mapping = idMappings.get(entityType)?.get(oldId);
if (!mapping) {
throw new Error(`No mapping found for ${entityType}:${oldId}`);
}
return mapping;
}
// ============================================================================
// STEP 1: MIGRATE USERS → CREATORS
// ============================================================================
async function migrateUsers() {
console.log("📊 Migrating users to creator things...");
const oldUsers = await sourceDB.users.findMany();
console.log(`Found ${oldUsers.length} users to migrate`);
const results = { success: 0, failed: 0, errors: [] };
for (let i = 0; i < oldUsers.length; i += BATCH_SIZE) {
const batch = oldUsers.slice(i, i + BATCH_SIZE);
for (const oldUser of batch) {
try {
const newCreator = {
type: "creator" as const,
name: oldUser.name,
properties: {
email: oldUser.email,
username: oldUser.email.split("@")[0],
displayName: oldUser.name,
bio: oldUser.bio || "",
niche: [],
expertise: [],
targetAudience: "",
totalFollowers: oldUser.followersCount || 0,
totalContent: 0,
totalRevenue: 0,
role: "org_user",
},
status: oldUser.isActive ? "active" : "inactive",
createdAt: oldUser.createdAt.getTime(),
updatedAt: Date.now(),
};
if (!DRY_RUN) {
const newId = await convex.mutation(
api.mutations.things.create,
newCreator,
);
await storeIdMapping("users", oldUser.id, newId);
}
results.success++;
if (results.success % 100 === 0) {
console.log(` ✅ Migrated ${results.success} users...`);
}
} catch (error) {
results.failed++;
results.errors.push({ oldId: oldUser.id, error: error.message });
}
}
}
console.log(
`✅ Users migration complete: ${results.success} success, ${results.failed} failed`,
);
return results;
}
// ============================================================================
// STEP 2: MIGRATE CONTENT → CONTENT THINGS
// ============================================================================
async function migrateContent() {
console.log("📊 Migrating content to thing types...");
const oldPosts = await sourceDB.posts.findMany();
console.log(`Found ${oldPosts.length} posts to migrate`);
const results = { success: 0, failed: 0, errors: [] };
for (const oldPost of oldPosts) {
try {
const newCreatorId = await getNewId("users", oldPost.authorId);
const contentType = determineContentType(oldPost);
const newContent = {
type: contentType,
name: oldPost.title,
properties: {
title: oldPost.title,
description: oldPost.excerpt,
body: oldPost.content,
format: oldPost.format || "text",
publishedAt: oldPost.publishedAt?.getTime(),
views: oldPost.views || 0,
likes: oldPost.likes || 0,
generatedBy: "human",
},
status: oldPost.published ? "published" : "draft",
createdAt: oldPost.createdAt.getTime(),
updatedAt: Date.now(),
};
if (!DRY_RUN) {
const contentId = await convex.mutation(
api.mutations.things.create,
newContent,
);
// Create authorship connection
await convex.mutation(api.mutations.connections.create, {
fromThingId: newCreatorId,
toThingId: contentId,
relationshipType: "authored",
createdAt: oldPost.createdAt.getTime(),
});
await storeIdMapping("posts", oldPost.id, contentId);
}
results.success++;
} catch (error) {
results.failed++;
results.errors.push({ oldId: oldPost.id, error: error.message });
}
}
console.log(
`✅ Content migration complete: ${results.success} success, ${results.failed} failed`,
);
return results;
}
// ============================================================================
// STEP 3: MIGRATE RELATIONSHIPS → CONNECTIONS
// ============================================================================
async function migrateRelationships() {
console.log("📊 Migrating relationships to connections...");
const oldFollows = await sourceDB.follows.findMany();
console.log(`Found ${oldFollows.length} follows to migrate`);
const results = { success: 0, failed: 0, errors: [] };
for (const oldFollow of oldFollows) {
try {
const newFollowerId = await getNewId("users", oldFollow.followerId);
const newFollowedId = await getNewId("users", oldFollow.followedId);
if (!DRY_RUN) {
await convex.mutation(api.mutations.connections.create, {
fromThingId: newFollowerId,
toThingId: newFollowedId,
relationshipType: "following",
createdAt: oldFollow.createdAt.getTime(),
});
}
results.success++;
} catch (error) {
results.failed++;
results.errors.push({
oldId: `${oldFollow.followerId}-${oldFollow.followedId}`,
error: error.message,
});
}
}
console.log(
`✅ Relationships migration complete: ${results.success} success, ${results.failed} failed`,
);
return results;
}
// ============================================================================
// MAIN MIGRATION FLOW
// ============================================================================
async function main() {
console.log("🚀 Starting ONE Platform Migration");
console.log(`Mode: ${DRY_RUN ? "DRY RUN" : "LIVE"}`);
console.log("=".repeat(60));
try {
const userResults = await migrateUsers();
const contentResults = await migrateContent();
const relationshipResults = await migrateRelationships();
console.log("\n" + "=".repeat(60));
console.log("📊 MIGRATION SUMMARY");
console.log("=".repeat(60));
console.log(
`Users: ${userResults.success} success, ${userResults.failed} failed`,
);
console.log(
`Content: ${contentResults.success} success, ${contentResults.failed} failed`,
);
console.log(
`Relationships: ${relationshipResults.success} success, ${relationshipResults.failed} failed`,
);
if (DRY_RUN) {
console.log("\n⚠️ This was a DRY RUN. No data was actually migrated.");
} else {
console.log("\n✅ Migration complete!");
}
} catch (error) {
console.error("\n❌ Migration failed:", error);
process.exit(1);
}
}
main();
```
**Running:**
```bash
# Dry run (safe, no changes)
DRY_RUN=true bun run scripts/migration/migrate-{source}.ts
# Live migration
DRY_RUN=false bun run scripts/migration/migrate-{source}.ts
```
## Verification Checklist
### Data Integrity Checks
```typescript
// scripts/migration/verify-migration.ts
async function verifyMigration() {
console.log("🔍 Verifying migration...");
const checks = [
verifyThingCounts(),
verifyConnectionIntegrity(),
verifyEventChronology(),
verifyKnowledgeLinks(),
];
const results = await Promise.all(checks);
results.forEach((result) => {
console.log(result.passed ? "✅" : "❌", result.name);
if (!result.passed) {
console.log(" Errors:", result.errors);
}
});
}
async function verifyThingCounts() {
const oldUserCount = await sourceDB.users.count();
const newCreatorCount = await convex.query(api.queries.things.countByType, {
type: "creator",
});
return {
name: "Thing counts match",
passed: oldUserCount === newCreatorCount,
errors:
oldUserCount !== newCreatorCount
? [`Expected ${oldUserCount}, got ${newCreatorCount}`]
: [],
};
}
async function verifyConnectionIntegrity() {
const connections = await convex.query(api.queries.connections.listAll);
const errors = [];
for (const conn of connections) {
const from = await convex.query(api.queries.things.get, {
id: conn.fromThingId,
});
const to = await convex.query(api.queries.things.get, {
id: conn.toThingId,
});
if (!from || !to) {
errors.push(
`Broken connection: ${conn._id} (${from ? "✓" : "✗"} → ${
to ? "✓" : "✗"
})`,
);
}
}
return {
name: "Connection integrity",
passed: errors.length === 0,
errors,
};
}
async function verifyEventChronology() {
const events = await convex.query(api.queries.events.listAll);
const errors = [];
for (let i = 1; i < events.length; i++) {
if (events[i].timestamp < events[i - 1].timestamp) {
errors.push(
`Event chronology broken: ${events[i]._id} before ${events[i - 1]._id}`,
);
}
}
return {
name: "Event chronology",
passed: errors.length === 0,
errors,
};
}
async function verifyKnowledgeLinks() {
const clones = await convex.query(api.queries.things.listByType, {
type: "ai_clone",
});
const errors = [];
for (const clone of clones) {
const knowledgeLinks = await convex.query(
api.queries.thingKnowledge.getByThing,
{ thingId: clone._id },
);
if (knowledgeLinks.length !== clone.properties.knowledgeBaseSize) {
errors.push(
`AI clone ${clone._id}: Expected ${clone.properties.knowledgeBaseSize} knowledge links, found ${knowledgeLinks.length}`,
);
}
}
return {
name: "Knowledge links",
passed: errors.length === 0,
errors,
};
}
```
## Common Mistakes to Avoid
### Migration Mistakes
1. **Migrating without inventory**
- ❌ Start coding immediately
- ✅ Document source system first, create comprehensive inventory
2. **Using wrong thing types**
- ❌ Generic "entity" or "user" type
- ✅ Use specific types: "creator", "audience_member", "ai_clone"
3. **Losing relationships**
- ❌ Only migrate things, ignore connections
- ✅ Create connections for all relationships, use proper connection types
4. **Skipping verification**
- ❌ Assume migration succeeded
- ✅ Run full verification suite, check counts and integrity
5. **No dry-run testing**
- ❌ Run live migration first time
- ✅ Always dry-run first, review output, fix errors
6. **Using "entities" terminology**
- ❌ Refer to "entities" in code and docs
- ✅ Use "things" throughout (matches ontology)
### AI Clone Mistakes
1. **Creating clone without knowledge**
- ❌ Create ai_clone thing with empty knowledge base
- ✅ Extract and chunk content first, then create clone with links
2. **Missing connection types**
- ❌ Only create the ai_clone thing
- ✅ Create clone_of, trained_on, and powers connections
3. **Not using thingKnowledge junction**
- ❌ Only high-level trained_on connections
- ✅ Create granular thingKnowledge links for each chunk
4. **Poor system prompts**
- ❌ Generic "You are an AI assistant" prompt
- ✅ Generate from creator profile: niche, expertise, audience, bio
5. **Forgetting events**
- ❌ Create clone silently
- ✅ Log clone_created, voice_cloned, appearance_cloned events
6. **Wrong knowledge types**
- ❌ Use "document" or "vector_only" for training data
- ✅ Use "chunk" type with embeddings for RAG
## Success Criteria
### Migration Success
- [x] All data transformed to 6-dimension ontology (things, connections, events, knowledge)
- [x] Thing counts match source system
- [x] All connections point to valid things (no orphaned records)
- [x] Event chronology is logical and complete
- [x] All verification checks pass
- [x] Feature parity achieved (everything that worked before still works)
- [x] Code uses new patterns (Convex, Effect.ts, shadcn/ui, React 19)
- [x] Documentation updated with migration notes
- [x] ID mappings preserved for reconciliation
- [x] All terminology uses "things" not "entities"
### AI Clone Success
- [x] AI clone thing created with correct type (`ai_clone`)
- [x] All required properties populated (voiceId, systemPrompt, knowledgeBaseSize, etc.)
- [x] Knowledge extracted and chunked from creator content
- [x] Embeddings generated for all chunks (1536-dim vectors)
- [x] Connection network created (clone_of, trained_on, powers)
- [x] thingKnowledge junction links created for all chunks
- [x] Events logged (clone_created, voice_cloned, appearance_cloned)
- [x] System prompt generated from creator profile
- [x] Voice and appearance cloned (or defaults set)
- [x] Status set correctly (draft → active after voice/appearance)
## Integration with Other Agents
### Works With
**Director Agent:** Receives migration projects assigned by director, reports completion status
**Backend Specialist:** Collaborates on Convex schema updates for migrated data types
**Frontend Specialist:** Provides component migration patterns for UI transformation
**Quality Agent:** Receives verification requirements, submits verification results
**Problem Solver Agent:** Consults when migration errors occur, implements proposed fixes
**Documenter Agent:** Provides migration documentation for knowledge base updates
## File Outputs
### Required Files
1. **Inventory Reports**
- `scripts/migration/inventory-{source}.md`
- Complete analysis of source system
2. **Mapping Documents**
- `scripts/migration/mappings.md`
- Old schema → new ontology mappings
3. **Migration Scripts**
- `scripts/migration/migrate-{source}.ts`
- Automated transformation code
4. **Verification Scripts**
- `scripts/migration/verify-migration.ts`
- Data integrity validation
5. **ID Mappings**
- `scripts/migration/id-mappings.json`
- Old ID → New ID reference
6. **Migration Report**
- `scripts/migration/report.md`
- Success/failure summary, known issues
7. **Verification Results**
- `scripts/migration/verification-results.json`
- Check results, pass/fail status
## References
- **Ontology:** `/one/knowledge/ontology.yaml` (Version 1.0.0)
- **Thing Types:** 66 types defined in ontology
- **Connection Types:** 25 types, including clone_of, trained_on, powers
- **Event Types:** 67 types, including clone_created, voice_cloned
- **Knowledge Types:** chunk, label, document, vector_only
- **Agent Prompts Feature:** `/one/things/features/1-1-agent-prompts.md`
- **Workflow:** `/one/connections/workflow.md`
**Status:** Active and ready for migration projects
**Last Updated:** 2025-01-15
**Version:** 2.0.0 (Ontology-aligned)