// prompts.js — All AI prompts v4 (ATS-engineered) // ============================================================================ // LANGUAGE RULES: Analysis = Arabic. Everything else = ENGLISH ALWAYS. // // All identity facts come from PROFILE_DATA (profile_data.js). Nothing in this // file may hardcode a job title, a metric, a date or a contact detail. // ============================================================================ // ─── ATS methodology block ────────────────────────────────────────────────── // This is the part that actually moves the needle with parsers and recruiters. // It is injected into every CV/keyword-facing prompt. const ATS_METHOD = ` ATS METHODOLOGY — APPLY ALL OF THIS: 1. ACCURATE TERMINOLOGY ATS systems differ; no universal score or guaranteed shortlist is available. If the job says "React Native", do not claim it from Flutter experience. Copy the job posting's EXACT wording for any skill I genuinely have. Do not paraphrase, do not use a synonym, do not pluralise differently. 2. DUAL FORM FOR ACRONYMS Write both forms on first use so either query matches: "Continuous Integration / Continuous Deployment (CI/CD)", "Application Programming Interface (API)", "Know Your Customer (KYC)". 3. TITLE ALIGNMENT The CV headline should closely mirror the job's title when that title is an honest description of my record. Recruiters and ATS both weight title match heavily. Never invent seniority. 4. KEYWORD FREQUENCY A critical keyword should appear 2-3 times across the document (summary, skills, and at least one experience bullet) — never stuffed, always inside a real sentence that describes something I actually did. 5. BULLET FORMULA (XYZ) Every bullet: "Accomplished [X] as measured by [Y] by doing [Z]." Start with a strong past-tense verb. Lead with the outcome, not the task. Prefer a real number over an adjective every single time. 6. HARD SKILLS BEAT SOFT SKILLS Prioritise tools, languages, frameworks, protocols and platforms. Soft skills ("team player", "communicator") are near-worthless to an ATS — include only where the job explicitly names them as a requirement. 7. PARSER SAFETY No tables, no columns, no text boxes, no graphics, no headers/footers, no icons or symbols in place of words. Standard section headings only ("Professional Summary", "Technical Skills", "Professional Experience", "Education"). Dates as "MMM YYYY – MMM YYYY". 8. HONEST GAP HANDLING If the job requires something I do not have, do NOT insert it. Instead find the closest genuine adjacent experience and name it accurately.`; // ─── Integrity rules, generated from the profile ──────────────────────────── function buildIntegrityRules(P) { const b = P.boundaries; return ` STRICT INTEGRITY RULES — VIOLATING ANY OF THESE INVALIDATES THE OUTPUT: 1. NEVER invent a skill, tool, framework, employer, metric or certification that is not present in MY PROFESSIONAL PROFILE below. 2. NEVER claim to have held these titles (they may be discussed as target roles): ${P.forbiddenTitles.join(', ')}. Allowed titles only: ${P.allowedTitles.join(', ')}. 3. NEVER claim any of the following — I have no production experience with them: ${b.neverClaim.join(', ')}. 4. MY GENUINE STRENGTHS (lead with these): ${b.strongIn.map(s => ' • ' + s).join('\n')} 5. MY HONEST LIMITS — these constrain what you may WRITE, not what I may apply to automatically. Never claim them. If a missing capability is mandatory and central, flag an honest mismatch: ${b.limitedIn.map(s => ' • ' + s).join('\n')} 6. Every number I use must be one of the real metrics in my profile. Do not round up, do not extrapolate, do not invent new ones. 7. Do not mention: ${P.voice.neverMention.join('; ')}. 8. Banned phrasing (reads as AI-generated or as filler): ${P.voice.banned.join(' / ')}.`; } // ─── Apply/skip policy, generated from the profile ────────────────────────── // Injected ONLY into the decision-making tabs (analysis, ATS verdict, benefits, // bulk pre-screen). Without it the model treats the CV-integrity boundaries as a // rejection checklist and skips almost everything. function buildApplyPolicy(P) { const a = P.applyPolicy; if (!a) return ''; const supporting = (P.supportingSkills && P.supportingSkills.length) ? ` SKILL vs. TARGET — do not confuse the two. Having a skill is not wanting the job: ${P.supportingSkills.map(s => ' ~ ' + s).join('\n')} Roles I am seeking: ${P.targetRoles.join(' | ')}. ` : ''; return `${supporting} APPLY / SKIP POLICY — THIS GOVERNS THE VERDICT: Evaluate independently for relevance, responsibility and evidence. Never force an APPLY quota. Mandatory engineering people-management experience is a real gap, not a wording problem. These are additional hard blockers: ${a.hardBlockers.map(s => ' ✗ ' + s).join('\n')} The following are explicitly NOT reasons to skip. If one of these is the worst thing about the posting, the verdict is APPLY or APPLY WITH EDITS — never skip: ${a.notBlockers.map(s => ' ✓ ' + s).join('\n')} CALIBRATION: ${a.calibration} Distinguish a learnable gap, missing information and a mandatory unmet requirement. Rewording a CV does not create experience. For leadership roles assess decision authority, business outcome, hands-on scope, team-management requirements and resources.`; } function buildPromptV2(tab, job, userProfile, language) { const P = (typeof PROFILE_DATA !== 'undefined') ? PROFILE_DATA : null; if (!P) { console.error('[LJA] profile_data.js not loaded — prompts will be degraded.'); } const id = P ? P.identity : {}; const analysisLang = 'Respond ENTIRELY in Arabic. All headings, explanations and bullets MUST be in Arabic, and RTL.'; // Cap the description here rather than letting the transport truncate the // whole prompt. Truncation at the transport layer cuts from the END, which is // exactly where the job posting and the required output format live. const MAX_DESCRIPTION_CHARS = 7000; const rawDescription = job.description || 'No description available'; const description = rawDescription.length > MAX_DESCRIPTION_CHARS ? rawDescription.slice(0, MAX_DESCRIPTION_CHARS) + '\n[description truncated]' : rawDescription; const ctx = [ 'Job Title: ' + (job.jobTitle || 'Not specified'), 'Company: ' + (job.company || 'Not specified'), 'Location: ' + (job.location || 'Not specified'), 'Type: ' + (job.jobType || 'Not specified'), 'Description:\n' + description, (job.skills && job.skills.length) ? 'Required Skills: ' + job.skills.join(', ') : '' ].filter(Boolean).join('\n'); // Prefer the stored/edited profile; fall back to the rendered source of truth. const profileText = (userProfile && userProfile.trim()) ? userProfile : (typeof renderProfileText === 'function' ? renderProfileText() : ''); const prof = 'MY PROFESSIONAL PROFILE:\n' + profileText; const co = job.company || 'this company'; const STRICT_RULES = P ? buildIntegrityRules(P) : ''; const APPLY_POLICY = P ? buildApplyPolicy(P) : ''; const Pr = {}; // ── TAB: Analysis (Arabic) ──────────────────────────────────────────────── Pr.analysis = `You are my career strategist — on MY side of the table, not the employer's. Your job is to get me shortlisted, not to gatekeep. Be honest, be brief, and be actionable. ${analysisLang} CRITICAL FRAMING: I am a ${P ? P.identity.primaryTitle : 'Senior Software Engineer'} (${P ? P.identity.positioningLine : ''}) who has taken platforms from zero to live operations, owning mobile, backend, geo-infrastructure, security and DevOps. Position that end-to-end 0-to-1 ownership as the core advantage. Do NOT downgrade my experience to "just a developer". Evaluate hands-on CTO and founding technology leadership opportunities when the mandate fits. Do not claim a past CTO title or engineering people management. Distinguish technical ownership from direct reports. DO NOT recount my history or summarise my profile back to me. Be actionable. ${APPLY_POLICY} ${STRICT_RULES} ${prof} JOB POSTING: ${ctx} Respond in this EXACT structure: ## 🎯 القرار: [تقدّم / تقدّم بعد تعديل السيفي / لا تتقدّم] [اشرح الدليل على الملاءمة أو المانع. عند غياب وصف كافٍ اكتب اطلب توضيحاً. إدارة فرق هندسية لم تحدث؛ لا تعالجها بإعادة صياغة السيفي.] ## 📊 الملاءمة: قوية / جزئية / غير واضحة / ضعيفة [المتطلبات المتحققة والمفقودة ومصدر كل منها؛ ليست احتمالية قبول. افصل CTO تنفيذي عن إدارة فرق كبيرة.] ## ✅ نقاط القوة هنا - [نقطة 1 — اربطها بمتطلب محدد من الإعلان] - [نقطة 2] - [نقطة 3] ## ❌ الفجوات وكيف نغطيها - [فجوة 1 — التصنيف: مانع فعلي / قابلة للمعالجة / شكلية — ثم كيف أغطيها في السيفي أو المقابلة] - [فجوة 2 — نفس الشيء] ## 📝 تعديلات السيفي المطلوبة - [ما الذي يجب إبرازه] - [ما الذي يجب تقليصه] ## 🔑 كلمات مفتاحية ناقصة يجب إضافتها حرفياً - [4-6 كلمات منسوخة حرفياً من الإعلان]`; // ── TAB: Cover letter ───────────────────────────────────────────────────── Pr.coverletter = `You are an expert career writer. Write a COMPLETE, READY-TO-SEND cover letter. IMPORTANT: Write ENTIRELY in English regardless of the job posting language. ${STRICT_RULES} ${prof} JOB: ${ctx} FORMAT — follow EXACTLY: Dear ${co} Team, [PARAGRAPH 1 — HOOK (3 sentences max): A specific connection between my record and this role. Name the company. Open with something I BUILT, not with an intention to apply.] [PARAGRAPH 2 — PROOF (4-5 sentences): Match 3-4 of this job's stated requirements to my REAL achievements. Include numbers only when evidence supports them; never force one. Use "At Intaleq, I..." / "Building Tripz, I...". Mirror the job's exact technical vocabulary where it matches my real skills.] [PARAGRAPH 3 — CLOSE (2-3 sentences): Why THIS company specifically. Confident, non-needy call to action requesting a conversation.] Best regards, ${id.fullName} ${id.email} ${id.phone} CRITICAL RULES: - MUST be in English - NO brackets or placeholders in the final output — use ACTUAL names and data - Every sentence must be unusable for any other job posting - Under 300 words total - Tone: ${P ? P.voice.tone : 'direct and evidence-first'}`; // ── TAB: CV tips / LinkedIn optimisation ────────────────────────────────── Pr.cvtips = `You are an ATS specialist and LinkedIn optimisation expert. IMPORTANT: Respond ENTIRELY in English regardless of the job posting language. ${ATS_METHOD} ${STRICT_RULES} ${prof} JOB: ${ctx} Respond EXACTLY: ## LINKEDIN HEADLINE [One headline, UNDER 220 characters (LinkedIn's real limit — use the room). Format: