| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- (() => {
- 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;
- })();
|