#!/usr/bin/env node
/**
* Granular Analysis Test - Show complete hyper-granular content mining
*/
import { LearnService } from './modules/learn-service.js';
import { createLearnLogger } from './modules/utils/custom-logger.js';
const TEST_CONFIG = {
projectId: 'granular_test_' + Date.now(),
dataDir: process.env.FOREST_DATA_DIR || './.forest-data',
youtubeUrl: 'https://www.youtube.com/watch?v=scGlmUuq4WM'
};
class GranularAnalysisTest {
constructor() {
this.logger = createLearnLogger('GranularTest');
this.learnService = null;
}
async run() {
try {
console.log(`
š¬ HYPER-GRANULAR CONTENT ANALYSIS TEST
URL: ${TEST_CONFIG.youtubeUrl}
Goal: Extract maximum actionable detail for precise task generation
`);
await this.initializeServices();
const summaryData = await this.processAndAnalyze();
this.displayGranularAnalysis(summaryData);
await this.cleanup();
} catch (error) {
console.error('ā Test failed:', error.message);
throw error;
}
}
async initializeServices() {
this.learnService = new LearnService(TEST_CONFIG.dataDir, this.logger);
await this.learnService.initialize();
}
async processAndAnalyze() {
// Add and process the source
await this.learnService.addLearningSources(TEST_CONFIG.projectId, [TEST_CONFIG.youtubeUrl]);
await this.learnService.processLearningSources(TEST_CONFIG.projectId);
// Wait for processing
let attempts = 0;
while (attempts < 15) {
await this.sleep(2000);
const status = await this.learnService.getProcessingStatus(TEST_CONFIG.projectId);
if (!status.sources?.isProcessing) break;
attempts++;
}
// Get the detailed summary
const sources = await this.learnService.listLearningSources(TEST_CONFIG.projectId);
const completedSource = sources.find(s => s.status === 'completed');
if (!completedSource) {
throw new Error('No completed source found');
}
return await this.learnService.getLearningSummary(TEST_CONFIG.projectId, completedSource.id);
}
displayGranularAnalysis(summaryData) {
console.log('šÆ HYPER-GRANULAR ANALYSIS RESULTS\n');
console.log('=' * 80);
// Basic Info
console.log('š BASIC INFORMATION:');
console.log(`Title: ${summaryData.metadata?.title}`);
console.log(`Author: ${summaryData.metadata?.author}`);
console.log(`Difficulty: ${summaryData.difficulty}`);
console.log(`Estimated Duration: ${summaryData.estimatedDuration}`);
console.log(`Granularity Score: ${summaryData.metadata?.granularityScore}/10`);
console.log(`Actionability Score: ${summaryData.metadata?.actionabilityScore}/10`);
console.log('');
// Actionable Steps
if (summaryData.actionableSteps?.length > 0) {
console.log('šÆ ACTIONABLE STEPS:');
summaryData.actionableSteps.forEach((step, index) => {
console.log(`${index + 1}. [${step.type.toUpperCase()}] ${step.action}`);
if (step.sequence) console.log(` Sequence: ${step.sequence}`);
console.log(` Confidence: ${Math.round(step.confidence * 100)}%`);
console.log('');
});
}
// Specific Techniques
if (summaryData.specificTechniques?.length > 0) {
console.log('š ļø SPECIFIC TECHNIQUES:');
summaryData.specificTechniques.forEach((tech, index) => {
console.log(`${index + 1}. ${tech.name} (${tech.type})`);
console.log(` Confidence: ${Math.round(tech.confidence * 100)}%`);
console.log('');
});
}
// Tools and Resources
if (summaryData.toolsAndResources?.length > 0) {
console.log('š§ TOOLS & RESOURCES:');
summaryData.toolsAndResources.forEach((resource, index) => {
console.log(`${index + 1}. [${resource.type.toUpperCase()}] ${resource.name}`);
console.log(` Confidence: ${Math.round(resource.confidence * 100)}%`);
console.log('');
});
}
// Time-Based Breakdown
if (summaryData.timeBasedBreakdown?.length > 0) {
console.log('ā° TIME-BASED BREAKDOWN:');
summaryData.timeBasedBreakdown.forEach((segment, index) => {
console.log(`${index + 1}. ${segment.timestamp} - ${segment.content}`);
console.log(` Confidence: ${Math.round(segment.confidence * 100)}%`);
console.log('');
});
}
// Skill Progression
if (summaryData.skillProgression?.length > 0) {
console.log('š SKILL PROGRESSION:');
summaryData.skillProgression.forEach((skill, index) => {
console.log(`${index + 1}. [${skill.level.toUpperCase()}] ${skill.skill}`);
console.log(` Confidence: ${Math.round(skill.confidence * 100)}%`);
console.log('');
});
}
// Common Mistakes
if (summaryData.commonMistakes?.length > 0) {
console.log('ā ļø COMMON MISTAKES:');
summaryData.commonMistakes.forEach((mistake, index) => {
console.log(`${index + 1}. ${mistake.mistake}`);
console.log(` Type: ${mistake.type}`);
console.log(` Confidence: ${Math.round(mistake.confidence * 100)}%`);
console.log('');
});
}
// Prerequisites
if (summaryData.prerequisites?.length > 0) {
console.log('š PREREQUISITES:');
summaryData.prerequisites.forEach((prereq, index) => {
console.log(`${index + 1}. ${prereq.requirement}`);
console.log(` Type: ${prereq.type}`);
console.log(` Confidence: ${Math.round(prereq.confidence * 100)}%`);
console.log('');
});
}
// Measurable Outcomes
if (summaryData.measurableOutcomes?.length > 0) {
console.log('šÆ MEASURABLE OUTCOMES:');
summaryData.measurableOutcomes.forEach((outcome, index) => {
console.log(`${index + 1}. ${outcome.outcome}`);
console.log(` Type: ${outcome.type}`);
console.log(` Measurable: ${outcome.measurable ? 'Yes' : 'No'}`);
console.log(` Confidence: ${Math.round(outcome.confidence * 100)}%`);
console.log('');
});
}
// Enhanced Tags
console.log('š·ļø ENHANCED TAGS:');
console.log(summaryData.tags?.join(', ') || 'None');
console.log('');
// Forest Integration Preview
console.log('š² FOREST HTA INTEGRATION:');
console.log('This granular data enables Forest to generate specific tasks like:');
console.log('');
if (summaryData.actionableSteps?.length > 0) {
console.log('š EXAMPLE GENERATED TASKS:');
summaryData.actionableSteps.slice(0, 3).forEach((step, index) => {
console.log(`Task ${index + 1}: ${step.action}`);
console.log(` - Type: ${step.type}`);
console.log(` - Estimated time: 15-30 minutes`);
console.log(` - Prerequisites: Basic guitar knowledge`);
console.log('');
});
}
console.log('š GRANULAR ANALYSIS COMPLETE!');
console.log('This level of detail enables Forest to create highly specific,');
console.log('actionable tasks instead of generic "learn guitar" instructions.');
}
async cleanup() {
const sources = await this.learnService.listLearningSources(TEST_CONFIG.projectId);
if (sources.length > 0) {
const sourceIds = sources.map(s => s.id);
await this.learnService.deleteLearningSources(TEST_CONFIG.projectId, sourceIds);
}
await this.learnService.shutdown();
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Run the test
if (import.meta.url === `file://${process.argv[1]}`) {
const test = new GranularAnalysisTest();
process.on('SIGINT', async () => {
console.log('\nš Test interrupted');
try {
await test.cleanup();
} catch (error) {
console.error('Cleanup error:', error.message);
}
process.exit(0);
});
test.run().catch(error => {
console.error('ā Granular analysis test failed:', error.message);
process.exit(1);
});
}