Add Phase 3 migration: project documentation

- migrate-project-docs-batch.mjs: 60 files across 23 projects
- migrate-cf-docs-batch.mjs: ClaudeFramework documentation
- migrate-plans-batch.mjs: Session plan files
- 017_fix_archives_embedding_dimension.sql: Fix vector dimension
- run-migration.js: Node.js migration runner utility

Total migrated: 332 files, 8.85MB with semantic embeddings

Fixes: CF-277
This commit is contained in:
Christian Gick
2026-01-19 14:09:03 +02:00
parent 6c497ec6c5
commit eb6b51837f
5 changed files with 794 additions and 0 deletions

168
migrate-plans-batch.mjs Normal file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env node
/**
* Automated batch migration of ~/.claude/plans/*.md to task-mcp database
*
* Run from task-mcp directory: node migrate-plans-batch.mjs
*/
import { readFileSync, readdirSync, renameSync, mkdirSync, existsSync, statSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
import dotenv from 'dotenv';
import { archiveAdd } from './dist/tools/archives.js';
// Load environment
dotenv.config();
// Configuration
const PLANS_DIR = join(homedir(), '.claude', 'plans');
const BACKUP_DIR = join(PLANS_DIR, '.migrated-to-mcp');
const ALREADY_MIGRATED = [
'adaptive-enchanting-truffle.md',
'adaptive-sleeping-pearl.md'
];
/**
* Extract title from markdown content (first H1)
*/
function extractTitle(content, filename) {
const lines = content.split('\n');
for (const line of lines) {
if (line.startsWith('# ')) {
return line.slice(2).trim().substring(0, 500);
}
}
// Fallback to filename
return filename
.replace('.md', '')
.replace(/-/g, ' ')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
.substring(0, 500);
}
/**
* Migrate a single plan file
*/
async function migratePlan(filename) {
const filePath = join(PLANS_DIR, filename);
try {
const content = readFileSync(filePath, 'utf-8');
const title = extractTitle(content, filename);
const fileSize = statSync(filePath).size;
console.log(`\n[${new Date().toISOString().substring(11, 19)}] Migrating: ${filename}`);
console.log(` Title: ${title}`);
console.log(` Size: ${Math.round(fileSize / 1024)}KB`);
// Call archive_add
const result = await archiveAdd({
project: 'CF',
archive_type: 'session',
title,
content,
original_path: filePath,
file_size: fileSize
});
console.log(` ✓ Migrated successfully`);
// Move to backup
if (!existsSync(BACKUP_DIR)) {
mkdirSync(BACKUP_DIR, { recursive: true });
}
const backupPath = join(BACKUP_DIR, filename);
renameSync(filePath, backupPath);
console.log(` ✓ Moved to backup`);
return { success: true, filename, title, fileSize };
} catch (error) {
console.error(` ✗ Error: ${error.message}`);
return { success: false, filename, error: error.message };
}
}
/**
* Main migration function
*/
async function main() {
console.log('================================================================================');
console.log('Batch Migration: ~/.claude/plans/*.md → task-mcp database');
console.log('================================================================================\n');
// Get all plan files
const allFiles = readdirSync(PLANS_DIR).filter(f => f.endsWith('.md'));
const filesToMigrate = allFiles.filter(f => !ALREADY_MIGRATED.includes(f));
console.log(`Total plan files: ${allFiles.length}`);
console.log(`Already migrated: ${ALREADY_MIGRATED.length}`);
console.log(`To migrate: ${filesToMigrate.length}\n`);
if (filesToMigrate.length === 0) {
console.log('✓ All files already migrated!');
return;
}
console.log('Starting migration...\n');
const results = {
success: [],
failed: []
};
// Migrate each file
for (let i = 0; i < filesToMigrate.length; i++) {
const filename = filesToMigrate[i];
const result = await migratePlan(filename);
if (result.success) {
results.success.push(result);
} else {
results.failed.push(result);
}
// Progress indicator
const progress = Math.round(((i + 1) / filesToMigrate.length) * 100);
console.log(` Progress: ${i + 1}/${filesToMigrate.length} (${progress}%)`);
// Small delay to avoid overwhelming the database
await new Promise(resolve => setTimeout(resolve, 50));
}
// Summary
console.log('\n================================================================================');
console.log('Migration Complete');
console.log('================================================================================\n');
console.log(`✓ Successfully migrated: ${results.success.length} files`);
console.log(`✗ Failed: ${results.failed.length} files`);
if (results.failed.length > 0) {
console.log('\nFailed files:');
results.failed.forEach(f => {
console.log(` - ${f.filename}: ${f.error}`);
});
}
console.log(`\nBackup location: ${BACKUP_DIR}`);
console.log('Original files can be restored if needed.');
// Calculate total size
const totalSize = results.success.reduce((sum, r) => sum + (r.fileSize || 0), 0);
console.log(`\nTotal data migrated: ${Math.round(totalSize / 1024 / 1024 * 100) / 100}MB`);
}
// Run migration
main()
.then(() => {
console.log('\n✓ Migration script completed successfully');
process.exit(0);
})
.catch(error => {
console.error('\n✗ Migration script failed:', error);
console.error(error.stack);
process.exit(1);
});