(() => { const scope = 'local-guest'; function seedIpOperatorScenario(scenario = 'ready') { const now = new Date().toISOString(); const user = { objectId: scope, username: 'ip-operator-e2e', displayName: 'IP Operator E2E', role: 'user', createdAt: now, }; clearIpOperatorData(); localStorage.setItem('videoWorkflow.authSession', JSON.stringify({ token: 'ip-operator-e2e-token', user })); localStorage.setItem('tiktok.currentTab', 'ip-operator'); sessionStorage.clear(); if (scenario === 'empty') return { scenario, profileId: '', planId: '' }; const profileId = `ip_profile_e2e_${scenario}`; const planId = `ip_plan_e2e_${scenario}`; const profile = createProfile(profileId, now); const plan = createPlan({ scenario, profileId, planId, now }); localStorage.setItem(`tiktok.ipOperator.profiles.${scope}`, JSON.stringify([profileId])); localStorage.setItem(`tiktok.ipOperator.profile.${profileId}.${scope}`, JSON.stringify(profile)); localStorage.setItem(`tiktok.ipOperator.plans.${scope}`, JSON.stringify([planId])); localStorage.setItem(`tiktok.ipOperator.plan.${planId}.${scope}`, JSON.stringify(plan)); localStorage.setItem(`tiktok.ipOperator.activeProfileId.${scope}`, profileId); localStorage.setItem(`tiktok.ipOperator.auditTrail.${scope}`, JSON.stringify([{ id: 'ip_audit_e2e_switch', action: 'switch_profile', entityType: 'profile', entityId: profileId, userId: scope, createdAt: now, summary: `Switch current IP profile: ${profileId}`, }])); return { scenario, profileId, planId }; } function clearIpOperatorData() { for (const key of Object.keys(localStorage)) { if ( key.startsWith('tiktok.ipOperator.') || key === 'videoWorkflow.authSession' || key === 'videoWorkflow.topicPool.items' ) { localStorage.removeItem(key); } } } function createProfile(id, now) { return { id, userId: scope, name: 'E2E IP Operator Profile', stage: 'started', identity: 'Traditional industry consultant for local business owners', industry: 'Local service business', targetAudience: 'Owners who need practical IP-driven content and trust conversion', audiencePainPoints: ['Content looks like advertising', 'No stable topic system'], productsOrServices: 'IP positioning and content operation consulting', personalStories: ['Helped a local service team turn cases into short video topics'], expertise: ['Positioning', 'Topic planning', 'Script diagnosis'], expressionStyle: ['Direct', 'Practical'], boundaries: ['No exaggerated income promise'], goals: ['Build trust', 'Collect consultation leads'], questionnaire: [], createdAt: now, updatedAt: now, }; } function createPlan({ scenario, profileId, planId, now }) { const topics = createTopics(); const scripts = createScripts(topics); const failed = scenario === 'failed'; const needsInput = scenario === 'needs_input'; return { id: planId, userId: scope, profileId, status: failed ? 'failed' : needsInput ? 'needs_input' : 'ready', generationProgress: [ { stage: 'intake_summary', label: 'Intake summary', status: 'completed', durationMs: 120 }, { stage: 'diagnosis', label: 'Diagnosis', status: failed ? 'failed' : 'completed', durationMs: 120, failureCode: failed ? 'llm_malformed_json' : undefined, errorMessage: failed ? 'Malformed JSON in diagnosis stage' : undefined }, ], qualityCheck: { overallScore: needsInput ? 64 : failed ? 40 : 88, positioningClarityScore: needsInput ? 60 : 90, audienceClarityScore: needsInput ? 62 : 86, evidenceSupportScore: needsInput ? 50 : 84, benchmarkTransferScore: needsInput ? 58 : 88, topicUsabilityScore: needsInput ? 65 : 91, passed: !needsInput && !failed, blockingIssues: needsInput ? ['Missing real cases and proof material'] : failed ? ['Generation failed before quality gate'] : [], improvementSuggestions: needsInput ? ['Add two real client cases before syncing topics'] : ['Validate the first three full scripts with real material.'], }, intakeSummary: { identitySummary: 'Local business IP operator', audienceSummary: 'Traditional business owners', advantageSummary: 'Can translate business cases into practical content', businessGoalSummary: 'Build trust and collect consultation leads', missingInputs: needsInput ? [{ type: 'case', description: 'Add real client before-after cases', priority: 'high' }] : [], }, diagnosis: failed ? undefined : { positioningStatement: 'A practical operator who turns local business experience into trusted owner IP content.', targetAudience: { summary: 'Owners who need short video content but do not want to become ad accounts.', painPoints: ['No topic system', 'Content lacks trust', 'Hard to convert'], }, marketOpportunity: 'Many local businesses have real cases but lack content packaging.', ipType: 'Operator partner', personaTags: ['Practical', 'Case-driven', 'Trust-first'], differentiation: 'Turns benchmark hot points into positioning-matched topics instead of copying formats.', contentTracks: ['Positioning diagnosis', 'Trust cases', 'Conversion path'], monetizationPath: 'Consultation and operation service leads.', risks: ['Avoid exaggerated conversion promises'], alternativeDirections: ['Focus on one local industry first'], missingInputs: needsInput ? [{ type: 'case', description: 'Add real proof material', priority: 'high' }] : [], }, benchmarkAnalyses: failed ? [] : [{ benchmarkId: 'benchmark_e2e_1', accountName: 'Benchmark Owner Account', positioning: 'Direct business advice for owners', contentColumns: ['Pain point diagnosis', 'Case breakdown'], viralPatterns: ['Question hook', 'Concrete contrast'], scriptStructure: 'Hook - pain - viewpoint - case - action', conversionPath: 'Content trust to consultation', borrowablePoints: ['Direct question hooks', 'Case contrast'], nonCopyablePoints: ['Personal background', 'Exact industry claims'], migrationDirection: 'Use the hook logic, replace the case and judgement with this IP assets.', fitScore: 86, }], opportunityMap: failed ? [] : [{ id: 'ip_opp_e2e_1', type: 'Trust diagnosis', fitScore: 90, reason: 'Matches audience pain and available expertise.', audiencePainPoint: 'Users do not trust product-only content.', requiredMaterials: ['Before-after case'], extendableTopics: ['Ad account problem', 'Trust building'], riskBoundary: 'No guaranteed result claim.', }], topics: failed ? [] : topics, scripts: failed ? [] : scripts, sevenDayTestPlan: failed ? [] : topics.slice(0, 7).map((topic, index) => ({ day: index + 1, topicId: topic.id, topicTitle: topic.title, testGoal: 'Validate hook clarity and trust response.', contentType: topic.trafficLayer, shootingFocus: 'Talk to camera with one real scenario.', observeMetrics: ['Completion', 'Comment quality', 'Consultation intent'], reviewQuestions: ['Did users understand the pain?', 'Was the CTA too hard?'], })), thirtyDayDirection: failed ? undefined : { columnStructure: [ { column: 'Positioning diagnosis', ratio: 40, role: 'Trust entry' }, { column: 'Trust content', ratio: 35, role: 'Relationship building' }, { column: 'Conversion path', ratio: 25, role: 'Lead collection' }, ], weeklyFocus: ['Validate hooks', 'Add case material', 'Test conversion CTA', 'Review topic columns'], materialDirections: ['Customer doubt list', 'Before-after cases', 'Service process screenshots'], iterationPath: ['Keep high-comment questions', 'Rewrite weak hooks', 'Promote proven topics'], }, missingInputs: needsInput ? [{ type: 'case', description: 'Add real client before-after cases', priority: 'high' }] : [], errorMessage: failed ? 'Generation stopped because diagnosis JSON was malformed.' : undefined, createdAt: now, updatedAt: now, }; } function createTopics() { return Array.from({ length: 12 }, (_, index) => ({ id: `ip_topic_e2e_${index + 1}`, title: index === 0 ? 'Why owner IP should not look like an ad account' : `Owner IP trust topic ${index + 1}`, column: index % 3 === 0 ? 'Positioning diagnosis' : index % 3 === 1 ? 'Trust content' : 'Conversion path', trafficLayer: index < 4 ? 'vertical' : index < 8 ? 'conversion' : 'broad', contentGoal: 'Help the target user understand the trust problem and next action', priority: index < 4 ? 'high' : index < 9 ? 'medium' : 'low', fitReason: 'Derived from benchmark hooks and adapted to this IP positioning', source: 'Benchmark migration', requiredMaterials: ['Real case', 'Service before-after comparison'], scriptStatus: index < 3 ? 'full' : 'outline', riskNote: 'Avoid hard selling and exaggerated claims', })); } function createScripts(topics) { return topics.map((topic, index) => ({ id: `ip_script_e2e_${index + 1}`, topicId: topic.id, type: index < 3 ? 'full' : 'outline', title: topic.title, hook: 'If your account keeps introducing products, users will treat it as advertising.', painPoint: 'The content has information but no trust context.', viewpoint: 'Owner IP must first transmit judgement, not product inventory.', caseOrMethod: 'Use one benchmark hook, one real scenario, and one conversion boundary.', goldenSentence: 'Trust comes before transaction.', closingCta: 'Save this and check whether your next video is selling or building trust.', fullScript: index < 3 ? 'Opening: many owner accounts look professional but still fail to convert. Middle: users do not reject business, they reject content that only pushes products. Example: when a local service owner changed from product introductions to decision-making stories, consultation quality improved. Ending: the next video should answer one real customer doubt before mentioning the product.' : '', shootingTips: ['Talk to camera', 'Use one service case'], subtitleHighlights: ['Do not sell first', 'Show judgement first'], replaceableSlots: ['Insert local case'], riskNote: 'Do not claim guaranteed conversion.', })); } window.__seedIpOperatorScenario = seedIpOperatorScenario; })();