resuml 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +77 -18
- package/README.md +5 -0
- package/bin/resuml +3 -2
- package/data/jobs/companies.json +76 -0
- package/dist/ats/index.d.ts +7 -0
- package/dist/ats/index.js +8 -0
- package/dist/ats/index.js.map +1 -0
- package/dist/chunk-C2JG5KF4.js +2088 -0
- package/dist/chunk-C2JG5KF4.js.map +1 -0
- package/dist/chunk-G4AN2EMI.js +461 -0
- package/dist/chunk-G4AN2EMI.js.map +1 -0
- package/dist/chunk-QBCXFLW6.js +686 -0
- package/dist/chunk-QBCXFLW6.js.map +1 -0
- package/dist/{chunk-R4MD5YMV.js → chunk-QR77BRMN.js} +154 -2434
- package/dist/chunk-QR77BRMN.js.map +1 -0
- package/dist/chunk-YVC53STN.js +997 -0
- package/dist/chunk-YVC53STN.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +6 -424
- package/dist/index.js +20 -775
- package/dist/index.js.map +1 -1
- package/dist/jobs/index.d.ts +158 -0
- package/dist/jobs/index.js +23 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/mcp/server.js +134 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/index.d.ts +67 -0
- package/dist/skills/index.js +13 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/types/index.d.ts +343 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types-B_jASYU4.d.ts +81 -0
- package/package.json +33 -3
- package/dist/chunk-R4MD5YMV.js.map +0 -1
- package/src/types/resume.ts +0 -344
- package/src/types/schema.d.ts +0 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ats/checks/parsing.ts","../src/ats/i18n/en.ts","../src/ats/i18n/de.ts","../src/ats/i18n/index.ts","../src/ats/checks/yoe.ts","../src/ats/checks/recruiter.ts","../src/ats/jdMatcher.ts","../src/ats/roleFamily.ts","../src/ats/checks/match.ts","../src/ats/scoring.ts","../src/utils/config.ts","../src/ats/index.ts"],"sourcesContent":["import type { ResumeSchema } from '../../types/resume';\nimport type { CheckResult } from '../types';\n\ntype CheckFn = (resume: ResumeSchema, language: string) => CheckResult;\n\nconst ISO_DATE = /^\\d{4}(-\\d{2})?(-\\d{2})?$/;\n\nexport const conventionalSections: CheckFn = (resume) => {\n const required = ['basics', 'work', 'education'] as const;\n const missing = required.filter((s) => {\n const v = resume[s];\n if (Array.isArray(v)) return v.length === 0;\n return v === undefined;\n });\n const passed = missing.length === 0;\n return {\n id: 'conventional-sections',\n tier: 'parsing',\n weight: 'high',\n status: passed ? 'pass' : 'fail',\n score: Math.round(((required.length - missing.length) / required.length) * 100),\n message: passed\n ? 'All conventional sections present.'\n : `Missing required sections: ${missing.join(', ')}.`,\n hints: passed ? [] : [`Add ${missing.join(', ')} to your YAML.`],\n };\n};\n\nexport const dateFormatConsistency: CheckFn = (resume) => {\n const all: { date: string; where: string }[] = [];\n for (const w of resume.work || []) {\n if (w.startDate) all.push({ date: w.startDate, where: `work \"${w.name || ''}\".startDate` });\n if (w.endDate) all.push({ date: w.endDate, where: `work \"${w.name || ''}\".endDate` });\n }\n for (const e of resume.education || []) {\n if (e.startDate)\n all.push({ date: e.startDate, where: `education \"${e.institution || ''}\".startDate` });\n if (e.endDate)\n all.push({ date: e.endDate, where: `education \"${e.institution || ''}\".endDate` });\n }\n if (all.length === 0) {\n return {\n id: 'date-format-consistency',\n tier: 'parsing',\n weight: 'medium',\n status: 'skipped',\n score: 0,\n message: 'No dates to check.',\n hints: [],\n };\n }\n const bad = all.filter((d) => !ISO_DATE.test(d.date));\n const passed = bad.length === 0;\n return {\n id: 'date-format-consistency',\n tier: 'parsing',\n weight: 'medium',\n status: passed ? 'pass' : bad.length <= 1 ? 'warn' : 'fail',\n score: Math.round(((all.length - bad.length) / all.length) * 100),\n message: passed\n ? 'All dates use ISO-8601 format.'\n : `Non-ISO dates: ${bad\n .slice(0, 3)\n .map((b) => `${b.where}=${b.date}`)\n .join('; ')}.`,\n hints: passed ? [] : ['Use YYYY-MM or YYYY-MM-DD for every date field.'],\n };\n};\n\nexport const contactInBody: CheckFn = (resume) => {\n const b = resume.basics;\n const checks: { ok: boolean; field: string }[] = [\n { ok: !!b?.name, field: 'name' },\n { ok: !!b?.email, field: 'email' },\n { ok: !!b?.phone, field: 'phone' },\n { ok: !!b?.location?.city, field: 'location.city' },\n ];\n const missing = checks.filter((c) => !c.ok).map((c) => c.field);\n const passed = missing.length === 0;\n return {\n id: 'contact-in-body',\n tier: 'parsing',\n weight: 'high',\n status: passed ? 'pass' : 'fail',\n score: Math.round(((checks.length - missing.length) / checks.length) * 100),\n message: passed\n ? 'Contact information present in basics.'\n : `Missing contact fields: ${missing.join(', ')}.`,\n hints: passed ? [] : [`Add ${missing.join(', ')} to basics.`],\n };\n};\n\nexport const reverseChronOrder: CheckFn = (resume) => {\n const work = resume.work || [];\n if (work.length < 2) {\n return {\n id: 'reverse-chron-order',\n tier: 'parsing',\n weight: 'medium',\n status: 'skipped',\n score: 100,\n message: 'Single or no work entry.',\n hints: [],\n };\n }\n let outOfOrder = 0;\n for (let i = 0; i < work.length - 1; i++) {\n const curr = work[i];\n const next = work[i + 1];\n const a = curr?.startDate || '';\n const b = next?.startDate || '';\n if (a && b && a < b) outOfOrder++;\n }\n const passed = outOfOrder === 0;\n return {\n id: 'reverse-chron-order',\n tier: 'parsing',\n weight: 'medium',\n status: passed ? 'pass' : 'fail',\n score: passed ? 100 : Math.max(0, 100 - outOfOrder * 50),\n message: passed\n ? 'Work entries in reverse-chronological order.'\n : `${outOfOrder} pair(s) out of reverse-chronological order.`,\n hints: passed ? [] : ['Reorder work[] so the most recent role is first.'],\n };\n};\n\nexport const educationComplete: CheckFn = (resume) => {\n const edu = resume.education || [];\n if (edu.length === 0) {\n return {\n id: 'education-complete',\n tier: 'parsing',\n weight: 'low',\n status: 'fail',\n score: 0,\n message: 'No education entries.',\n hints: ['Add at least one education entry with institution, area, and studyType.'],\n };\n }\n const incomplete = edu.filter((e) => !e.institution || !e.area || !e.studyType);\n const passed = incomplete.length === 0;\n return {\n id: 'education-complete',\n tier: 'parsing',\n weight: 'low',\n status: passed ? 'pass' : 'fail',\n score: Math.round(((edu.length - incomplete.length) / edu.length) * 100),\n message: passed\n ? 'All education entries complete.'\n : `${incomplete.length} education entry(ies) missing institution/area/studyType.`,\n hints: passed ? [] : ['Fill in institution, area and studyType for every education entry.'],\n };\n};\n\nexport const allParsingChecks = [\n conventionalSections,\n dateFormatConsistency,\n contactInBody,\n reverseChronOrder,\n educationComplete,\n];\n","export interface LanguageData {\n actionVerbs: string[];\n pronouns: string[];\n stopWords: string[];\n}\n\nconst en: LanguageData = {\n actionVerbs: [\n // Leadership & Management\n 'achieved',\n 'administered',\n 'advanced',\n 'allocated',\n 'approved',\n 'assigned',\n 'authorized',\n 'chaired',\n 'consolidated',\n 'coordinated',\n 'delegated',\n 'directed',\n 'established',\n 'executed',\n 'headed',\n 'hired',\n 'hosted',\n 'led',\n 'managed',\n 'mentored',\n 'motivated',\n 'orchestrated',\n 'organized',\n 'oversaw',\n 'planned',\n 'presided',\n 'prioritized',\n 'produced',\n 'recruited',\n 'spearheaded',\n 'supervised',\n // Technical & Engineering\n 'architected',\n 'automated',\n 'built',\n 'coded',\n 'configured',\n 'debugged',\n 'deployed',\n 'designed',\n 'developed',\n 'devised',\n 'engineered',\n 'implemented',\n 'installed',\n 'integrated',\n 'launched',\n 'maintained',\n 'migrated',\n 'modernized',\n 'optimized',\n 'overhauled',\n 'programmed',\n 'prototyped',\n 'refactored',\n 'reengineered',\n 'resolved',\n 'restructured',\n 'revamped',\n 'scaled',\n 'shipped',\n 'standardized',\n 'streamlined',\n 'tested',\n 'troubleshot',\n 'upgraded',\n // Achievement & Impact\n 'accelerated',\n 'accomplished',\n 'boosted',\n 'completed',\n 'contributed',\n 'converted',\n 'decreased',\n 'delivered',\n 'doubled',\n 'earned',\n 'eliminated',\n 'exceeded',\n 'expanded',\n 'expedited',\n 'generated',\n 'grew',\n 'improved',\n 'increased',\n 'maximized',\n 'minimized',\n 'outperformed',\n 'pioneered',\n 'recovered',\n 'reduced',\n 'saved',\n 'simplified',\n 'solved',\n 'surpassed',\n 'transformed',\n 'tripled',\n // Communication & Collaboration\n 'advised',\n 'advocated',\n 'briefed',\n 'collaborated',\n 'communicated',\n 'consulted',\n 'convinced',\n 'counseled',\n 'defined',\n 'demonstrated',\n 'documented',\n 'educated',\n 'facilitated',\n 'guided',\n 'influenced',\n 'informed',\n 'instructed',\n 'liaised',\n 'negotiated',\n 'partnered',\n 'persuaded',\n 'presented',\n 'promoted',\n 'proposed',\n 'published',\n 'recommended',\n 'represented',\n 'trained',\n // Analysis & Research\n 'analyzed',\n 'assessed',\n 'audited',\n 'benchmarked',\n 'calculated',\n 'compared',\n 'compiled',\n 'conducted',\n 'discovered',\n 'evaluated',\n 'examined',\n 'explored',\n 'forecasted',\n 'identified',\n 'inspected',\n 'interpreted',\n 'investigated',\n 'mapped',\n 'measured',\n 'modeled',\n 'monitored',\n 'quantified',\n 'researched',\n 'reviewed',\n 'surveyed',\n 'synthesized',\n 'tracked',\n 'validated',\n 'verified',\n // Creation & Innovation\n 'conceptualized',\n 'crafted',\n 'created',\n 'customized',\n 'formulated',\n 'founded',\n 'initiated',\n 'innovated',\n 'introduced',\n 'invented',\n 'originated',\n 'shaped',\n ],\n pronouns: ['i', 'me', 'my', 'mine', 'myself', 'we', 'our', 'ours'],\n stopWords: [\n // Articles & determiners\n 'a',\n 'an',\n 'the',\n 'and',\n 'or',\n 'but',\n 'in',\n 'on',\n 'at',\n 'to',\n 'for',\n 'of',\n 'with',\n 'by',\n 'from',\n 'is',\n 'was',\n 'are',\n 'were',\n 'be',\n 'been',\n 'being',\n 'have',\n 'has',\n 'had',\n 'do',\n 'does',\n 'did',\n 'will',\n 'would',\n 'could',\n 'should',\n 'may',\n 'might',\n 'shall',\n 'can',\n 'this',\n 'that',\n 'these',\n 'those',\n 'it',\n 'its',\n 'as',\n 'if',\n 'not',\n 'no',\n 'so',\n 'up',\n 'out',\n 'about',\n 'into',\n 'over',\n 'after',\n 'before',\n 'between',\n 'under',\n 'above',\n 'below',\n 'all',\n 'each',\n 'every',\n 'both',\n 'few',\n 'more',\n 'most',\n 'other',\n 'some',\n 'such',\n 'than',\n 'too',\n 'very',\n // Pronouns & possessives (also checked by pronoun check, but filter from JD keywords)\n 'you',\n 'your',\n 'yours',\n 'yourself',\n 'we',\n 'our',\n 'ours',\n 'ourselves',\n 'they',\n 'them',\n 'their',\n 'theirs',\n 'he',\n 'she',\n 'his',\n 'her',\n 'hers',\n 'who',\n 'whom',\n 'whose',\n 'which',\n 'what',\n 'where',\n 'when',\n 'how',\n 'why',\n // Common JD filler words (not meaningful for skill matching)\n 'able',\n 'also',\n 'across',\n 'already',\n 'always',\n 'among',\n 'any',\n 'apply',\n 'become',\n 'believe',\n 'best',\n 'bring',\n 'change',\n 'come',\n 'committed',\n 'company',\n 'comfortable',\n 'critical',\n 'current',\n 'day',\n 'desired',\n 'either',\n 'end',\n 'ensure',\n 'environment',\n 'equal',\n 'even',\n 'excellent',\n 'exciting',\n 'exceptional',\n 'expected',\n 'experience',\n 'fast',\n 'field',\n 'find',\n 'first',\n 'focused',\n 'follow',\n 'get',\n 'give',\n 'go',\n 'going',\n 'good',\n 'great',\n 'group',\n 'grow',\n 'growing',\n 'growth',\n 'help',\n 'here',\n 'high',\n 'highly',\n 'ideal',\n 'impact',\n 'important',\n 'include',\n 'includes',\n 'including',\n 'industry',\n 'interested',\n 'job',\n 'join',\n 'just',\n 'keep',\n 'key',\n 'know',\n 'large',\n 'latest',\n 'lead',\n 'level',\n 'like',\n 'location',\n 'long',\n 'look',\n 'looking',\n 'love',\n 'make',\n 'many',\n 'much',\n 'must',\n 'need',\n 'new',\n 'next',\n 'offer',\n 'one',\n 'only',\n 'open',\n 'opportunity',\n 'order',\n 'others',\n 'own',\n 'pace',\n 'part',\n 'partner',\n 'passionate',\n 'people',\n 'per',\n 'play',\n 'plus',\n 'position',\n 'preferred',\n 'provide',\n 'put',\n 'qualifications',\n 'quickly',\n 'range',\n 'related',\n 'required',\n 'requirements',\n 'requirement',\n 'responsible',\n 'responsibilities',\n 'responsibility',\n 'result',\n 'right',\n 'role',\n 'run',\n 'same',\n 'see',\n 'seek',\n 'seeking',\n 'set',\n 'several',\n 'since',\n 'skills',\n 'someone',\n 'start',\n 'state',\n 'still',\n 'strong',\n 'success',\n 'successful',\n 'support',\n 'sure',\n 'take',\n 'team',\n 'then',\n 'there',\n 'thing',\n 'think',\n 'through',\n 'time',\n 'together',\n 'top',\n 'truly',\n 'try',\n 'two',\n 'type',\n 'use',\n 'used',\n 'using',\n 'value',\n 'want',\n 'way',\n 'well',\n 'while',\n 'within',\n 'without',\n 'work',\n 'working',\n 'world',\n 'would',\n 'year',\n 'years',\n // Section headers & structural words (not technical skills)\n 'description',\n 'overview',\n 'summary',\n 'duties',\n 'bachelor',\n 'bachelors',\n 'master',\n 'masters',\n 'degree',\n 'phd',\n 'minimum',\n 'preferred',\n 'implement',\n 'process',\n 'robust',\n 'consistent',\n 'operations',\n // URL/email/domain fragments\n 'http',\n 'https',\n 'www',\n 'com',\n 'org',\n 'net',\n 'mailto',\n // Resume/YAML schema field names (in case raw YAML is pasted)\n 'name',\n 'keywords',\n 'highlights',\n 'startdate',\n 'enddate',\n 'website',\n 'profiles',\n 'basics',\n 'position',\n 'institution',\n 'studytype',\n 'fluency',\n 'issuer',\n 'network',\n 'username',\n 'countrycode',\n 'region',\n // Generic nouns that aren't skills\n 'product',\n 'company',\n 'service',\n 'services',\n 'platform',\n 'solutions',\n 'ability',\n 'opportunity',\n 'candidate',\n 'applicant',\n 'position',\n 'salary',\n 'compensation',\n 'benefits',\n 'perks',\n 'bonus',\n 'development',\n 'management',\n 'knowledge',\n 'modern',\n 'advanced',\n 'practices',\n 'nice',\n 'technologies',\n 'technology',\n 'frameworks',\n 'framework',\n 'tools',\n 'data',\n 'based',\n 'contribute',\n 'contributions',\n 'migration',\n 'leading',\n 'source',\n 'visit',\n // Common verbs & verb forms (not technical skills, supplement action verbs list)\n 'collaborate',\n 'collaborating',\n 'collaboratively',\n 'communicate',\n 'communicating',\n 'contributing',\n 'coordinate',\n 'coordinating',\n 'demonstrate',\n 'demonstrating',\n 'design',\n 'designing',\n 'designed',\n 'develop',\n 'developing',\n 'developed',\n 'drive',\n 'driving',\n 'driven',\n 'enable',\n 'enabling',\n 'evaluate',\n 'evaluating',\n 'execute',\n 'executing',\n 'facilitate',\n 'facilitating',\n 'identify',\n 'identifying',\n 'influence',\n 'influencing',\n 'interact',\n 'interacting',\n 'lead',\n 'leverage',\n 'leveraging',\n 'manage',\n 'managing',\n 'mentor',\n 'mentoring',\n 'operate',\n 'operating',\n 'optimize',\n 'optimizing',\n 'participate',\n 'participating',\n 'report',\n 'reporting',\n 'solve',\n 'solving',\n 'understand',\n 'understanding',\n // Common adjectives & descriptors (not technical skills)\n 'fluent',\n 'proficient',\n 'deep',\n 'solid',\n 'proven',\n 'hands-on',\n 'detail-oriented',\n 'results-driven',\n 'self-motivated',\n 'proactive',\n 'creative',\n 'innovative',\n 'dynamic',\n 'strategic',\n 'analytical',\n 'collaborative',\n 'effective',\n 'efficient',\n 'reliable',\n 'flexible',\n 'adaptable',\n 'motivated',\n 'dedicated',\n 'capable',\n 'qualified',\n 'diverse',\n 'inclusive',\n 'global',\n 'local',\n 'remote',\n 'hybrid',\n 'onsite',\n 'full-time',\n 'part-time',\n 'contract',\n 'permanent',\n // Role titles & department names (not skills themselves)\n 'designer',\n 'designers',\n 'developer',\n 'developers',\n 'engineer',\n 'engineers',\n 'manager',\n 'managers',\n 'director',\n 'analyst',\n 'analysts',\n 'architect',\n 'architects',\n 'consultant',\n 'consultants',\n 'specialist',\n 'specialists',\n 'coordinator',\n 'lead',\n 'principal',\n 'staff',\n 'junior',\n 'mid',\n 'department',\n 'organization',\n 'division',\n 'stakeholder',\n 'stakeholders',\n 'client',\n 'clients',\n 'customer',\n 'customers',\n // Date & time words\n 'date',\n 'dates',\n 'month',\n 'months',\n 'week',\n 'weeks',\n 'daily',\n 'weekly',\n 'monthly',\n 'quarterly',\n 'annual',\n 'annually',\n // More generic words that aren't skills\n 'code',\n 'coding',\n 'url',\n 'contact',\n 'information',\n 'apply',\n 'application',\n 'review',\n 'reviews',\n 'quality',\n 'scale',\n 'scalable',\n 'system',\n 'systems',\n 'solution',\n 'feature',\n 'features',\n 'project',\n 'projects',\n 'build',\n 'building',\n 'deliver',\n 'delivery',\n 'cross-functional',\n ],\n};\n\nexport default en;\n","import type { LanguageData } from './en';\n\nconst de: LanguageData = {\n actionVerbs: [\n // Führung & Management\n 'geleitet',\n 'geführt',\n 'koordiniert',\n 'organisiert',\n 'verwaltet',\n 'delegiert',\n 'beaufsichtigt',\n 'betreut',\n 'eingestellt',\n 'motiviert',\n 'verantwortet',\n 'gesteuert',\n 'überwacht',\n 'priorisiert',\n 'geplant',\n // Technik & Entwicklung\n 'entwickelt',\n 'implementiert',\n 'programmiert',\n 'konfiguriert',\n 'automatisiert',\n 'deployt',\n 'gebaut',\n 'entworfen',\n 'integriert',\n 'migriert',\n 'modernisiert',\n 'optimiert',\n 'refaktoriert',\n 'skaliert',\n 'standardisiert',\n 'getestet',\n 'aufgebaut',\n 'eingeführt',\n 'bereitgestellt',\n 'umgesetzt',\n // Leistung & Ergebnisse\n 'verbessert',\n 'gesteigert',\n 'reduziert',\n 'beschleunigt',\n 'erreicht',\n 'übertroffen',\n 'erweitert',\n 'vereinfacht',\n 'gelöst',\n 'transformiert',\n 'erhöht',\n 'verdoppelt',\n 'verdreifacht',\n 'generiert',\n 'gespart',\n 'maximiert',\n 'minimiert',\n 'eliminiert',\n 'geliefert',\n 'abgeschlossen',\n // Kommunikation & Zusammenarbeit\n 'beraten',\n 'präsentiert',\n 'dokumentiert',\n 'geschult',\n 'trainiert',\n 'vermittelt',\n 'kommuniziert',\n 'verhandelt',\n 'zusammengearbeitet',\n 'unterstützt',\n 'gefördert',\n 'empfohlen',\n 'vorgestellt',\n 'publiziert',\n // Analyse & Forschung\n 'analysiert',\n 'bewertet',\n 'evaluiert',\n 'untersucht',\n 'erforscht',\n 'identifiziert',\n 'gemessen',\n 'überwacht',\n 'validiert',\n 'verifiziert',\n 'geprüft',\n 'verglichen',\n 'recherchiert',\n 'quantifiziert',\n // Kreation & Innovation\n 'konzipiert',\n 'erstellt',\n 'gestaltet',\n 'initiiert',\n 'innoviert',\n 'eingeführt',\n 'gegründet',\n 'formuliert',\n ],\n pronouns: [\n 'ich',\n 'mich',\n 'mir',\n 'mein',\n 'meine',\n 'meinem',\n 'meiner',\n 'meines',\n 'wir',\n 'unser',\n 'unsere',\n ],\n stopWords: [\n 'ein',\n 'eine',\n 'einer',\n 'eines',\n 'einem',\n 'der',\n 'die',\n 'das',\n 'den',\n 'dem',\n 'des',\n 'und',\n 'oder',\n 'aber',\n 'in',\n 'an',\n 'auf',\n 'zu',\n 'für',\n 'von',\n 'mit',\n 'bei',\n 'aus',\n 'ist',\n 'war',\n 'sind',\n 'waren',\n 'wird',\n 'wurde',\n 'werden',\n 'hat',\n 'hatte',\n 'haben',\n 'hatten',\n 'sein',\n 'kann',\n 'könnte',\n 'soll',\n 'sollte',\n 'muss',\n 'musste',\n 'darf',\n 'diese',\n 'dieser',\n 'dieses',\n 'diesem',\n 'diesen',\n 'als',\n 'wenn',\n 'nicht',\n 'kein',\n 'keine',\n 'so',\n 'auch',\n 'noch',\n 'schon',\n 'nach',\n 'vor',\n 'über',\n 'unter',\n 'zwischen',\n 'durch',\n 'ohne',\n 'um',\n 'bis',\n 'alle',\n 'jede',\n 'jeder',\n 'jedes',\n 'mehr',\n 'viel',\n 'sehr',\n ],\n};\n\nexport default de;\n","import en from './en';\nimport de from './de';\nimport type { LanguageData } from './en';\n\nexport type { LanguageData };\n\nconst languages: Record<string, LanguageData> = { en, de };\n\nexport function getLanguageData(language: string): LanguageData {\n return languages[language] ?? languages['en'] ?? en;\n}\n","import type { ResumeSchema } from '../../types/resume';\n\nexport function computeYoeYears(work: ResumeSchema['work']): number {\n const ranges = (work || [])\n .filter((w) => w.startDate)\n .map((w) => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const s = new Date(w.startDate!).getTime();\n const e = w.endDate ? new Date(w.endDate).getTime() : Date.now();\n return [s, e] as [number, number];\n })\n .sort((a, b) => a[0] - b[0]);\n if (ranges.length === 0) return 0;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const merged: [number, number][] = [ranges[0]!];\n for (let i = 1; i < ranges.length; i++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const last = merged[merged.length - 1]!;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const curr = ranges[i]!;\n if (curr[0] <= last[1]) last[1] = Math.max(last[1], curr[1]);\n else merged.push(curr);\n }\n const ms = merged.reduce((sum, [s, e]) => sum + (e - s), 0);\n return ms / (1000 * 60 * 60 * 24 * 365.25);\n}\n","import type { ResumeSchema } from '../../types/resume';\nimport type { CheckResult, AtsConfig } from '../types';\nimport { getLanguageData } from '../i18n/index';\nimport { computeYoeYears } from './yoe';\n\ntype CheckFn = (resume: ResumeSchema, language: string, cfg: AtsConfig) => CheckResult;\n\nconst wordCount = (s: string) => s.trim().split(/\\s+/).filter(Boolean).length;\nconst firstWord = (s: string) =>\n s\n .trim()\n .split(/\\s+/)[0]\n ?.toLowerCase()\n .replace(/[^a-zA-ZäöüßÄÖÜàáâãéèêëíìîïóòôõúùûñç]/g, '') || '';\n\nfunction isSenior(resume: ResumeSchema, cfg: AtsConfig): boolean {\n return computeYoeYears(resume.work) >= cfg.thresholds.seniorYoeCutoff;\n}\n\nexport const summaryLength: CheckFn = (resume) => {\n const s = resume.basics?.summary?.trim();\n if (!s) {\n return {\n id: 'summary-length',\n tier: 'recruiter',\n weight: 'medium',\n status: 'fail',\n score: 0,\n message: 'No professional summary.',\n hints: ['Add a 2-4 sentence summary (20-50 words) to basics.summary.'],\n };\n }\n const w = wordCount(s);\n if (w >= 20 && w <= 50) {\n return {\n id: 'summary-length',\n tier: 'recruiter',\n weight: 'medium',\n status: 'pass',\n score: 100,\n message: `Summary length good (${w} words).`,\n hints: [],\n };\n }\n if (w >= 10 && w <= 80) {\n return {\n id: 'summary-length',\n tier: 'recruiter',\n weight: 'medium',\n status: 'warn',\n score: 70,\n message: `Summary ${w < 20 ? 'short' : 'long'} (${w} words). Aim for 20-50.`,\n hints: [w < 20 ? 'Expand to 20-50 words.' : 'Trim to the most impactful 20-50 words.'],\n };\n }\n return {\n id: 'summary-length',\n tier: 'recruiter',\n weight: 'medium',\n status: 'fail',\n score: Math.max(0, 100 - Math.abs(w - 35) * 2),\n message: `Summary length ${w} words is far from target.`,\n hints: ['Rewrite the summary in 2-4 sentences (20-50 words).'],\n };\n};\n\nexport const actionVerbStart: CheckFn = (resume, language) => {\n const verbs = new Set(getLanguageData(language).actionVerbs);\n const all: { text: string; path: string }[] = [];\n (resume.work || []).forEach((w, i) => {\n (w.highlights || []).forEach((h, j) =>\n all.push({ text: h, path: `work[${i}].highlights[${j}]` })\n );\n });\n (resume.projects || []).forEach((p, i) => {\n (p.highlights || []).forEach((h, j) =>\n all.push({ text: h, path: `projects[${i}].highlights[${j}]` })\n );\n });\n if (all.length === 0) {\n return {\n id: 'action-verb-start',\n tier: 'recruiter',\n weight: 'medium',\n status: 'skipped',\n score: 0,\n message: 'No highlights.',\n hints: [],\n };\n }\n const without = all.filter((h) => !verbs.has(firstWord(h.text)));\n const passed = without.length === 0;\n return {\n id: 'action-verb-start',\n tier: 'recruiter',\n weight: 'medium',\n status: passed ? 'pass' : without.length / all.length > 0.3 ? 'fail' : 'warn',\n score: Math.round(((all.length - without.length) / all.length) * 100),\n message: passed\n ? 'All highlights start with action verbs.'\n : `${without.length} of ${all.length} highlights miss an action verb.`,\n hints: passed\n ? []\n : without\n .slice(0, 3)\n .map((h) => `${h.path}: start with an action verb instead of \"${firstWord(h.text)}\".`),\n };\n};\n\nconst QUANT_RE =\n /\\d+%?|\\$[\\d,]+|[\\d,]+\\+?\\s*(users|clients|customers|people|team|members|projects|applications|servers|services|endpoints|requests|transactions)/i;\n\nexport const quantificationDensity: CheckFn = (resume) => {\n const all: { text: string; path: string }[] = [];\n (resume.work || []).forEach((w, i) => {\n (w.highlights || []).forEach((h, j) =>\n all.push({ text: h, path: `work[${i}].highlights[${j}]` })\n );\n });\n (resume.projects || []).forEach((p, i) => {\n (p.highlights || []).forEach((h, j) =>\n all.push({ text: h, path: `projects[${i}].highlights[${j}]` })\n );\n });\n if (all.length === 0) {\n return {\n id: 'quantification-density',\n tier: 'recruiter',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'No highlights.',\n hints: [],\n };\n }\n const quantified = all.filter((h) => QUANT_RE.test(h.text));\n const ratio = quantified.length / all.length;\n const status = ratio >= 0.5 ? 'pass' : ratio >= 0.3 ? 'warn' : 'fail';\n return {\n id: 'quantification-density',\n tier: 'recruiter',\n weight: 'high',\n status,\n score: Math.min(100, Math.round(ratio * 200)),\n message: `${quantified.length}/${all.length} highlights quantified (${Math.round(ratio * 100)}%).`,\n hints:\n status === 'pass'\n ? []\n : all\n .filter((h) => !QUANT_RE.test(h.text))\n .slice(0, 3)\n .map((h) => `${h.path}: add a number/metric.`),\n };\n};\n\nexport const pronounLeakage: CheckFn = (resume, language) => {\n const set = new Set(getLanguageData(language).pronouns);\n const blocks: { text: string; path: string }[] = [];\n if (resume.basics?.summary) blocks.push({ text: resume.basics.summary, path: 'basics.summary' });\n (resume.work || []).forEach((w, i) => {\n if (w.summary) blocks.push({ text: w.summary, path: `work[${i}].summary` });\n (w.highlights || []).forEach((h, j) =>\n blocks.push({ text: h, path: `work[${i}].highlights[${j}]` })\n );\n });\n const hits: { pronoun: string; path: string }[] = [];\n for (const b of blocks) {\n for (const w of b.text.toLowerCase().split(/\\s+/)) {\n const clean = w.replace(/[^a-zA-ZäöüßÄÖÜ]/g, '');\n if (set.has(clean)) hits.push({ pronoun: clean, path: b.path });\n }\n }\n const passed = hits.length === 0;\n return {\n id: 'pronoun-leakage',\n tier: 'recruiter',\n weight: 'low',\n status: passed ? 'pass' : hits.length > 3 ? 'fail' : 'warn',\n score: passed ? 100 : Math.max(0, 100 - hits.length * 15),\n message: passed\n ? 'No first-person pronouns.'\n : `${hits.length} pronoun(s): ${[...new Set(hits.map((h) => h.pronoun))].join(', ')}.`,\n hints: passed\n ? []\n : hits.slice(0, 3).map((h) => `${h.path}: drop \"${h.pronoun}\" (convention, not ATS).`),\n };\n};\n\nexport const bulletsPerRole: CheckFn = (resume, _l, cfg) => {\n const work = resume.work || [];\n if (work.length === 0) {\n return {\n id: 'bullets-per-role',\n tier: 'recruiter',\n weight: 'medium',\n status: 'skipped',\n score: 0,\n message: 'No work entries.',\n hints: [],\n };\n }\n const senior = isSenior(resume, cfg);\n const min = cfg.thresholds.bulletsPerRole.min;\n const max = senior ? cfg.thresholds.bulletsPerRole.seniorMax : cfg.thresholds.bulletsPerRole.max;\n const offenders: { path: string; n: number }[] = [];\n work.forEach((w, i) => {\n const n = (w.highlights || []).length;\n if (n < min || n > max) offenders.push({ path: `work[${i}]`, n });\n });\n const passed = offenders.length === 0;\n return {\n id: 'bullets-per-role',\n tier: 'recruiter',\n weight: 'medium',\n status: passed\n ? 'pass'\n : work.length === 1\n ? 'warn'\n : offenders.length > work.length / 2\n ? 'fail'\n : 'warn',\n score: Math.round(((work.length - offenders.length) / work.length) * 100),\n message: passed\n ? `All roles have ${min}-${max} highlights.`\n : `${offenders.length} role(s) outside ${min}-${max} highlights.`,\n hints: passed\n ? []\n : offenders.slice(0, 3).map((o) => `${o.path}: ${o.n} highlights, target ${min}-${max}.`),\n };\n};\n\nexport const wordCountTotal: CheckFn = (resume, _l, cfg) => {\n const senior = isSenior(resume, cfg);\n const min = cfg.thresholds.wordCount.min;\n const max = senior ? cfg.thresholds.wordCount.seniorMax : cfg.thresholds.wordCount.max;\n const parts: string[] = [];\n if (resume.basics?.summary) parts.push(resume.basics.summary);\n for (const w of resume.work || []) {\n if (w.summary) parts.push(w.summary);\n parts.push(...(w.highlights || []));\n }\n for (const p of resume.projects || []) {\n if (p.description) parts.push(p.description);\n parts.push(...(p.highlights || []));\n }\n const total = wordCount(parts.join(' '));\n const passed = total >= min && total <= max;\n const status = passed ? 'pass' : total < min * 0.7 || total > max * 1.5 ? 'fail' : 'warn';\n return {\n id: 'word-count-total',\n tier: 'recruiter',\n weight: 'low',\n status,\n score: passed ? 100 : Math.max(0, 100 - Math.round(Math.abs(total - (min + max) / 2) / 10)),\n message: `Resume body: ${total} words (target ${min}-${max}${senior ? ', senior' : ''}).`,\n hints: passed\n ? []\n : [total < min ? 'Add more depth to highlights.' : 'Trim less impactful highlights.'],\n };\n};\n\nexport const highlightLength: CheckFn = (resume) => {\n const all: { text: string; path: string }[] = [];\n (resume.work || []).forEach((w, i) => {\n (w.highlights || []).forEach((h, j) =>\n all.push({ text: h, path: `work[${i}].highlights[${j}]` })\n );\n });\n if (all.length === 0) {\n return {\n id: 'highlight-length',\n tier: 'recruiter',\n weight: 'low',\n status: 'skipped',\n score: 0,\n message: 'No highlights.',\n hints: [],\n };\n }\n const long = all.filter((h) => wordCount(h.text) > 30);\n const passed = long.length === 0;\n return {\n id: 'highlight-length',\n tier: 'recruiter',\n weight: 'low',\n status: passed ? 'pass' : long.length / all.length > 0.3 ? 'fail' : 'warn',\n score: Math.round(((all.length - long.length) / all.length) * 100),\n message: passed\n ? 'All highlights at most 30 words.'\n : `${long.length} highlight(s) over 30 words.`,\n hints: passed ? [] : long.slice(0, 3).map((h) => `${h.path}: trim to 30 words or fewer.`),\n };\n};\n\nfunction isLinkedInUrl(url: string | undefined): boolean {\n if (!url) return false;\n try {\n const host = new URL(url).hostname.toLowerCase();\n return host === 'linkedin.com' || host.endsWith('.linkedin.com');\n } catch {\n return false;\n }\n}\n\nexport const hasLinkedin: CheckFn = (resume) => {\n const profiles = resume.basics?.profiles || [];\n const found = profiles.some(\n (p) => p.network?.toLowerCase() === 'linkedin' || isLinkedInUrl(p.url)\n );\n return {\n id: 'has-linkedin',\n tier: 'recruiter',\n weight: 'low',\n status: found ? 'pass' : 'warn',\n score: found ? 100 : 0,\n message: found ? 'LinkedIn profile present.' : 'No LinkedIn profile.',\n hints: found ? [] : ['Add a LinkedIn profile to basics.profiles.'],\n };\n};\n\nexport const skillsPopulated: CheckFn = (resume) => {\n const skills = resume.skills || [];\n const withKeywords = skills.filter((s) => (s.keywords?.length ?? 0) > 0);\n const passed = withKeywords.length >= 3;\n return {\n id: 'skills-populated',\n tier: 'recruiter',\n weight: 'medium',\n status: passed ? 'pass' : withKeywords.length < 2 ? 'fail' : 'warn',\n score: Math.min(100, Math.round((withKeywords.length / 3) * 100)),\n message: passed\n ? `${withKeywords.length} skill categories with keywords.`\n : `Only ${withKeywords.length} skill categories with keywords (need 3+).`,\n hints: passed ? [] : ['Add at least 3 skill categories with keywords.'],\n };\n};\n\nexport const allRecruiterChecks = [\n summaryLength,\n actionVerbStart,\n quantificationDensity,\n pronounLeakage,\n bulletsPerRole,\n wordCountTotal,\n highlightLength,\n hasLinkedin,\n skillsPopulated,\n];\n","import type { ResumeSchema } from '../types/resume';\nimport { getSkillIndex, type SkillMatch } from './skills';\n\ninterface AtsKeywordMatch {\n matched: string[];\n missing: string[];\n extra: string[];\n matchPercentage: number;\n}\n\n/**\n * Extract text content from a resume for skill matching.\n */\nfunction extractResumeText(resume: ResumeSchema): string {\n const parts: string[] = [];\n\n if (resume.basics?.summary) parts.push(resume.basics.summary);\n if (resume.basics?.label) parts.push(resume.basics.label);\n\n for (const w of resume.work || []) {\n if (w.position) parts.push(w.position);\n if (w.summary) parts.push(w.summary);\n parts.push(...(w.highlights || []));\n }\n for (const s of resume.skills || []) {\n if (s.name) parts.push(s.name);\n parts.push(...(s.keywords || []));\n }\n for (const p of resume.projects || []) {\n if (p.name) parts.push(p.name);\n if (p.description) parts.push(p.description);\n parts.push(...(p.highlights || []));\n }\n for (const e of resume.education || []) {\n if (e.area) parts.push(e.area);\n if (e.studyType) parts.push(e.studyType);\n parts.push(...(e.courses || []));\n }\n for (const c of resume.certificates || []) {\n if (c.name) parts.push(c.name);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Split JD into sections and identify which contain the actual requirements.\n * Skills mentioned in requirement sections get prioritized over skills only\n * mentioned in the company-blurb / benefits sections.\n */\nfunction splitJdSections(text: string): { requirementText: string; fullText: string } {\n const lines = text.split('\\n');\n const reqPatterns =\n /^(required|requirements?|minimum|preferred|qualifications?|must[\\s-]have|nice[\\s-]to[\\s-]have|what you.?ll|what we.?re looking|skills|technical|you.?ll need|responsibilities|you will)/i;\n const nonReqPatterns =\n /^(about|summary|who we are|our (company|team|mission)|description|overview|benefits|perks|compensation|salary)/i;\n\n let inReqSection = false;\n const reqLines: string[] = [];\n\n for (const line of lines) {\n const header = line\n .trim()\n .replace(/[:#*-]/g, '')\n .trim();\n if (reqPatterns.test(header)) inReqSection = true;\n else if (nonReqPatterns.test(header)) inReqSection = false;\n if (inReqSection) reqLines.push(line);\n }\n\n return {\n requirementText: reqLines.join('\\n'),\n fullText: text,\n };\n}\n\n/**\n * Rank skills found in the JD. Gives precedence to skills that appear in\n * requirement sections, are flagged as \"hot technologies\" by O*NET, or\n * appear multiple times.\n */\ninterface RankedSkill {\n canonical: string;\n occurrences: number;\n inRequirementSection: boolean;\n hot: boolean;\n score: number;\n}\n\nfunction rankSkills(fullMatches: SkillMatch[], requirementMatches: SkillMatch[]): RankedSkill[] {\n const reqIds = new Set(requirementMatches.map((m) => m.skill.id));\n return fullMatches\n .map((m) => {\n const inRequirementSection = reqIds.has(m.skill.id);\n const score =\n m.occurrences * 1.0 + (inRequirementSection ? 3.0 : 0) + (m.skill.hot ? 1.5 : 0);\n return {\n canonical: m.skill.canonical,\n occurrences: m.occurrences,\n inRequirementSection,\n hot: m.skill.hot,\n score,\n };\n })\n .sort((a, b) => {\n if (a.inRequirementSection !== b.inRequirementSection) return a.inRequirementSection ? -1 : 1;\n if (a.score !== b.score) return b.score - a.score;\n return a.canonical.localeCompare(b.canonical);\n });\n}\n\n/**\n * Match a job description against a resume using the bundled skills taxonomy.\n *\n * Extraction is positive-filter: only terms recognised as known skills surface\n * as keywords, so prose verbs (\"actually\", \"ship\", \"move\"), contractions\n * (\"doesn't\" → \"doesn\") and generic nouns never leak through.\n */\nexport function matchJobDescription(\n resume: ResumeSchema,\n jobDescription: string,\n _language: string = 'en'\n): AtsKeywordMatch {\n if (!jobDescription.trim()) {\n return { matched: [], missing: [], extra: [], matchPercentage: 0 };\n }\n\n const skillIndex = getSkillIndex();\n\n // Extract skills from the full JD + requirement-only section\n const fullMatches = skillIndex.scan(jobDescription);\n const { requirementText } = splitJdSections(jobDescription);\n const requirementMatches = requirementText.trim()\n ? skillIndex.scan(requirementText)\n : fullMatches;\n\n // Rank and cap: top 25 most relevant skills, prioritising requirements + hot\n const ranked = rankSkills(fullMatches, requirementMatches).slice(0, 25);\n\n // Skills in the resume\n const resumeText = extractResumeText(resume);\n const resumeMatches = skillIndex.scan(resumeText);\n const resumeSkillIds = new Set(resumeMatches.map((m) => m.skill.id));\n\n const matched: string[] = [];\n const missing: string[] = [];\n for (const r of ranked) {\n // Find the skill object by canonical name to resolve id\n const match = fullMatches.find((m) => m.skill.canonical === r.canonical);\n if (!match) continue;\n if (resumeSkillIds.has(match.skill.id)) matched.push(r.canonical);\n else missing.push(r.canonical);\n }\n\n const matchPercentage =\n ranked.length > 0 ? Math.round((matched.length / ranked.length) * 100) : 0;\n\n // Resume skills not referenced by the JD\n const jdSkillIds = new Set(fullMatches.map((m) => m.skill.id));\n const extra: string[] = [];\n for (const m of resumeMatches) {\n if (!jdSkillIds.has(m.skill.id)) extra.push(m.skill.canonical);\n }\n // Cap extras to avoid overwhelming the UI\n extra.splice(25);\n\n return { matched, missing, extra, matchPercentage };\n}\n","import type { ResumeSchema } from '../types/resume';\n\n/**\n * Coarse occupation classification. The ATS match tier otherwise measures\n * keyword overlap and resume hygiene, which lets a well-formatted engineering\n * resume score \"good\" against, say, a Technical Recruiter role just because the\n * JD mentions \"engineering\" a lot. Classifying both sides into a role family\n * and comparing them is the missing relevance signal.\n */\nexport type RoleFamily =\n | 'engineering'\n | 'data'\n | 'design'\n | 'product'\n | 'recruiting'\n | 'sales'\n | 'marketing'\n | 'legal'\n | 'finance'\n | 'support'\n | 'operations';\n\n/**\n * Substring signatures per family. Substring (not word-boundary) matching is\n * deliberate so \"engineers\"/\"engineering\" both count toward engineering. The\n * classifier relies on volume: a recruiting JD saturates recruiting terms even\n * when it mentions engineering repeatedly, so recruiting still wins.\n */\nconst SIGNATURES: Record<RoleFamily, string[]> = {\n engineering: [\n 'software engineer',\n 'engineer',\n 'developer',\n 'programmer',\n 'swe',\n 'backend',\n 'back-end',\n 'frontend',\n 'front-end',\n 'full stack',\n 'full-stack',\n 'devops',\n 'sre',\n 'site reliability',\n 'software development',\n 'microservices',\n 'codebase',\n ],\n data: [\n 'data scientist',\n 'data engineer',\n 'machine learning',\n 'ml engineer',\n 'data analyst',\n 'analytics engineer',\n 'mlops',\n ],\n design: [\n 'designer',\n 'ux ',\n 'ui designer',\n 'product design',\n 'graphic design',\n 'visual design',\n 'user research',\n ],\n product: ['product manager', 'product owner', 'program manager', 'product management'],\n recruiting: [\n 'recruiter',\n 'recruiting',\n 'recruitment',\n 'talent acquisition',\n 'sourcer',\n 'sourcing',\n 'full-cycle recruiting',\n 'candidate experience',\n 'hiring manager',\n 'people ops',\n 'human resources',\n ],\n sales: [\n 'account executive',\n 'business development',\n 'sales development',\n 'sales representative',\n 'quota',\n 'sdr',\n 'bdr',\n ],\n marketing: [\n 'marketing',\n 'growth marketing',\n 'demand generation',\n 'content marketing',\n 'brand manager',\n 'seo',\n ],\n legal: ['legal counsel', 'attorney', 'paralegal', 'lawyer', 'litigation', 'general counsel'],\n finance: ['accountant', 'accounting', 'controller', 'fp&a', 'financial analyst', 'bookkeeping'],\n support: [\n 'customer support',\n 'customer success',\n 'support specialist',\n 'technical support',\n 'help desk',\n ],\n operations: ['operations manager', 'business operations', 'supply chain', 'logistics'],\n};\n\nconst FAMILIES = Object.keys(SIGNATURES) as RoleFamily[];\n\nfunction countOccurrences(haystack: string, needle: string): number {\n let count = 0;\n let idx = haystack.indexOf(needle);\n while (idx !== -1) {\n count++;\n idx = haystack.indexOf(needle, idx + needle.length);\n }\n return count;\n}\n\nexport interface RoleFamilyResult {\n family: RoleFamily;\n score: number;\n /** Margin over the runner-up family. */\n margin: number;\n}\n\n/**\n * Classify text into a role family. `title` matches are weighted ×3 because a\n * job/role title is far more diagnostic than body prose.\n *\n * Returns null when no family clears a confidence bar (top score < 2 or it\n * doesn't beat the runner-up) — better to abstain than to force a label.\n */\nexport function classifyRoleFamily(body: string, title = ''): RoleFamilyResult | null {\n const b = body.toLowerCase();\n const t = title.toLowerCase();\n\n const scores = FAMILIES.map((family) => {\n let score = 0;\n for (const sig of SIGNATURES[family]) {\n score += countOccurrences(b, sig);\n score += countOccurrences(t, sig) * 3;\n }\n return { family, score };\n }).sort((a, b2) => b2.score - a.score);\n\n const top = scores[0];\n const second = scores[1];\n if (!top || top.score < 2) return null;\n const margin = top.score - (second?.score ?? 0);\n if (margin < 1) return null;\n\n return { family: top.family, score: top.score, margin };\n}\n\n/**\n * Engineering sub-specialty. \"Software engineer\" is too coarse: a Frontend\n * Architect and a Security Software Engineer are both `engineering` but are not\n * interchangeable. When a JD's title clearly demands one specialty the resume\n * doesn't evidence, that's a mismatch.\n */\nexport type Specialty =\n | 'frontend'\n | 'backend'\n | 'security'\n | 'ml'\n | 'mobile'\n | 'devops'\n | 'data'\n | 'embedded'\n | 'qa';\n\nconst SPECIALTY_SIGNATURES: Record<Specialty, string[]> = {\n frontend: ['frontend', 'front-end', 'front end', 'react', 'vue', 'angular', 'css', 'ui engineer', 'web developer', 'design system'],\n backend: ['backend', 'back-end', 'back end', 'server-side', 'microservices', 'api development', 'distributed systems'],\n security: ['security', 'appsec', 'application security', 'infosec', 'penetration', 'vulnerability', 'secure coding', 'cryptography', 'threat'],\n ml: ['machine learning', 'ml engineer', 'deep learning', 'nlp', 'computer vision', 'ai engineer', 'pytorch', 'tensorflow'],\n mobile: ['ios engineer', 'android engineer', 'mobile engineer', 'swift', 'kotlin', 'react native', 'flutter'],\n devops: ['devops', 'sre', 'site reliability', 'platform engineer', 'kubernetes', 'terraform', 'infrastructure engineer'],\n data: ['data engineer', 'etl', 'data pipeline', 'spark', 'hadoop', 'data warehouse'],\n embedded: ['embedded', 'firmware', 'rtos', 'microcontroller', 'bare metal'],\n qa: ['qa engineer', 'test engineer', 'sdet', 'automation testing', 'quality assurance'],\n};\n\nconst SPECIALTIES = Object.keys(SPECIALTY_SIGNATURES) as Specialty[];\n\n/** Single dominant specialty in text (title weighted ×3), or null if unclear. */\nexport function classifySpecialty(body: string, title = ''): Specialty | null {\n const b = body.toLowerCase();\n const t = title.toLowerCase();\n const scores = SPECIALTIES.map((sp) => {\n let score = 0;\n for (const sig of SPECIALTY_SIGNATURES[sp]) {\n score += countOccurrences(b, sig);\n score += countOccurrences(t, sig) * 3;\n }\n return { sp, score };\n }).sort((a, b2) => b2.score - a.score);\n const top = scores[0];\n const second = scores[1];\n if (!top || top.score < 2) return null;\n if (top.score - (second?.score ?? 0) < 1) return null;\n return top.sp;\n}\n\n/**\n * Return the resume's dominant specialties by score margin, in descending score order.\n *\n * Constants (verified against sparse-CV edge case: topScore=4, margin=min(3,max(2,1))=2,\n * threshold=2 -- a runner-up with score=1 is excluded, while topScore=4 itself qualifies):\n * SPECIALTY_MIN_SCORE = 4 -- minimum raw score to claim any specialty\n * TOP_MARGIN_FACTOR = 0.5 -- relative margin fraction\n * SPECIALTY_ABS_MARGIN = 3 -- absolute cap on margin\n */\nconst SPECIALTY_MIN_SCORE = 4;\nconst TOP_MARGIN_FACTOR = 0.5;\nconst SPECIALTY_ABS_MARGIN = 3;\n\nexport function resumeSpecialties(resume: ResumeSchema): Specialty[] {\n const text = resumeRoleText(resume).toLowerCase();\n const scored = SPECIALTIES.map((sp) => {\n let score = 0;\n for (const sig of SPECIALTY_SIGNATURES[sp]) score += countOccurrences(text, sig);\n return { sp, score };\n }).sort((a, b) => b.score - a.score);\n\n const top = scored[0];\n if (!top || top.score < SPECIALTY_MIN_SCORE) return [];\n\n const margin = Math.min(SPECIALTY_ABS_MARGIN, Math.max(TOP_MARGIN_FACTOR * top.score, 1));\n const threshold = top.score - margin;\n\n return scored.filter((s) => s.score >= threshold).map((s) => s.sp);\n}\n\n/** Concatenate the role-bearing text of a resume for classification. */\nexport function resumeRoleText(resume: ResumeSchema): string {\n const parts: string[] = [];\n if (resume.basics?.label) parts.push(resume.basics.label);\n if (resume.basics?.summary) parts.push(resume.basics.summary);\n for (const w of resume.work ?? []) {\n if (w.position) parts.push(w.position);\n if (w.summary) parts.push(w.summary);\n parts.push(...(w.highlights ?? []));\n }\n for (const s of resume.skills ?? []) {\n if (s.name) parts.push(s.name);\n parts.push(...(s.keywords ?? []));\n }\n return parts.join(' ');\n}\n","import type { ResumeSchema } from '../../types/resume';\nimport type { CheckResult, KnockoutSignal } from '../types';\nimport { matchJobDescription } from '../jdMatcher';\nimport { computeYoeYears } from './yoe';\nimport {\n classifyRoleFamily,\n classifySpecialty,\n resumeRoleText,\n resumeSpecialties,\n} from '../roleFamily';\n\ninterface MatchOpts {\n jobDescription?: string;\n /** Posting title, when available separately from the body (e.g. job search). */\n jobTitle?: string;\n}\n\ntype MatchCheckFn = (resume: ResumeSchema, language: string, opts: MatchOpts) => CheckResult;\n\nconst SENIORITY = /\\b(junior|senior|lead|staff|principal|head of|vp|chief)\\b/gi;\nconst STOPWORDS = new Set([\n 'a',\n 'an',\n 'the',\n 'of',\n 'at',\n 'for',\n 'in',\n 'on',\n 'to',\n 'with',\n 'and',\n 'or',\n]);\n\nfunction tokenize(s: string): string[] {\n return s\n .toLowerCase()\n .replace(SENIORITY, '')\n .replace(/[^a-z0-9 ]/g, ' ')\n .split(/\\s+/)\n .filter((w) => w && !STOPWORDS.has(w));\n}\n\nfunction jaccard(a: string[], b: string[]): number {\n const A = new Set(a),\n B = new Set(b);\n let inter = 0;\n for (const x of A) if (B.has(x)) inter++;\n const union = A.size + B.size - inter;\n return union === 0 ? 0 : inter / union;\n}\n\nfunction trimTitle(t: string): string {\n // Drop trailing \", X\" or \" - X\" segments that bring company/team noise into Jaccard.\n return t\n .trim()\n .replace(/\\s*[,\\-–—]\\s.*$/, '')\n .trim();\n}\n\nfunction extractJdTitle(jd: string): string | undefined {\n const lines = jd.split('\\n').slice(0, 8);\n for (const l of lines) {\n const m =\n l.match(/(?:role|position|title)[\\s:-]+(.+)/i) ||\n l.match(/looking for (?:an? )?(.+?)(?:\\s+with|\\s+to|$)/i);\n if (m?.[1]) return trimTitle(m[1]);\n }\n const fallback = lines.find((l) =>\n /\\b(engineer|developer|manager|designer|analyst|scientist|architect|lead)\\b/i.test(l)\n );\n return fallback ? trimTitle(fallback) : undefined;\n}\n\nexport const titleAlignment: MatchCheckFn = (resume, _l, { jobDescription, jobTitle }) => {\n if (!jobDescription) {\n return {\n id: 'title-alignment',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'No JD.',\n hints: [],\n };\n }\n const resumeTitle = resume.work?.[0]?.position || resume.basics?.label;\n // Prefer an explicitly-supplied posting title; fall back to mining the body.\n const jdTitle = jobTitle?.trim() ? trimTitle(jobTitle) : extractJdTitle(jobDescription);\n if (!resumeTitle || !jdTitle) {\n // Don't reward or punish on missing data — exclude from the tier score.\n return {\n id: 'title-alignment',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'Could not extract a title from the JD or resume.',\n hints: ['Set basics.label to your target title, or supply the posting title.'],\n };\n }\n const j = jaccard(tokenize(resumeTitle), tokenize(jdTitle));\n const status = j >= 0.6 ? 'pass' : j >= 0.3 ? 'warn' : 'fail';\n return {\n id: 'title-alignment',\n tier: 'match',\n weight: 'high',\n status,\n score: Math.round(j * 100),\n message: `Title overlap ${Math.round(j * 100)}% (resume \"${resumeTitle}\" vs JD \"${jdTitle}\").`,\n hints: status === 'pass' ? [] : [`Consider aligning basics.label closer to \"${jdTitle}\".`],\n };\n};\n\nconst EDU_RE = {\n 3: /\\b(phd|ph\\.?d|doctorate|doctoral)\\b/i,\n 2: /\\b(master|m\\.?s|m\\.?a|mba|graduate degree)\\b/i,\n 1: /\\b(bachelor|b\\.?s|b\\.?a|undergraduate)\\b/i,\n} as const;\n\nfunction eduLevel(text: string): number {\n if (!text) return 0;\n if (EDU_RE[3].test(text)) return 3;\n if (EDU_RE[2].test(text)) return 2;\n if (EDU_RE[1].test(text)) return 1;\n return 0;\n}\n\nexport const educationLevel: MatchCheckFn = (resume, _l, { jobDescription }) => {\n if (!jobDescription) {\n return {\n id: 'education-level',\n tier: 'match',\n weight: 'medium',\n status: 'skipped',\n score: 0,\n message: 'No JD.',\n hints: [],\n };\n }\n const required = eduLevel(jobDescription);\n if (required === 0) {\n return {\n id: 'education-level',\n tier: 'match',\n weight: 'medium',\n status: 'skipped',\n score: 0,\n message: 'JD does not specify education level.',\n hints: [],\n };\n }\n const have = Math.max(0, ...(resume.education || []).map((e) => eduLevel(e.studyType || '')));\n const passed = have >= required;\n return {\n id: 'education-level',\n tier: 'match',\n weight: 'medium',\n status: passed ? 'pass' : 'fail',\n score: passed ? 100 : Math.round((have / required) * 100),\n message: `Resume level ${have}, JD required ${required}.`,\n hints: passed ? [] : ['JD requires a higher degree level than the resume reports.'],\n };\n};\n\nconst YOE_RE = /(\\d+)\\s*(?:\\+|[-–—]\\s*\\d+|to\\s*\\d+)?\\s*years?/i;\n\nexport const yoeMatch: MatchCheckFn = (resume, _l, { jobDescription }) => {\n if (!jobDescription) {\n return {\n id: 'yoe-match',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'No JD.',\n hints: [],\n };\n }\n const m = jobDescription.match(YOE_RE);\n if (!m) {\n return {\n id: 'yoe-match',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'JD does not specify years requirement.',\n hints: [],\n };\n }\n const required = parseInt(m[1] ?? '0', 10);\n const have = Math.floor(computeYoeYears(resume.work || []));\n const status = have >= required ? 'pass' : have >= required - 1 ? 'warn' : 'fail';\n return {\n id: 'yoe-match',\n tier: 'match',\n weight: 'high',\n status,\n score: Math.min(100, Math.round((have / required) * 100)),\n message: `${have} YOE detected vs ${required} required.`,\n hints:\n status === 'pass' ? [] : ['Highlight relevant earlier roles or projects to fill the gap.'],\n };\n};\n\nexport const hardSkillOverlap: MatchCheckFn = (resume, language, { jobDescription }) => {\n if (!jobDescription) {\n return {\n id: 'hard-skill-overlap',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'No JD.',\n hints: [],\n };\n }\n const km = matchJobDescription(resume, jobDescription, language);\n const pct = km.matchPercentage;\n const status = pct >= 70 ? 'pass' : pct >= 50 ? 'warn' : 'fail';\n return {\n id: 'hard-skill-overlap',\n tier: 'match',\n weight: 'high',\n status,\n score: pct,\n message: `${km.matched.length}/${km.matched.length + km.missing.length} hard skills matched (${pct}%).`,\n hints:\n status === 'pass'\n ? []\n : km.missing.slice(0, 5).map((s) => `Add evidence of \"${s}\" to skills/highlights.`),\n };\n};\n\n/**\n * Occupation fit. Classifies the resume and the JD (title + body) into a coarse\n * role family and compares them. A hard mismatch (engineering resume vs a\n * recruiting role) is the single most important relevance signal and, unlike\n * the other checks, also caps the overall score in analyzeAts.\n */\nexport const roleFamilyMatch: MatchCheckFn = (resume, _l, { jobDescription, jobTitle }) => {\n if (!jobDescription) {\n return {\n id: 'role-family-match',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'No JD.',\n hints: [],\n };\n }\n const jd = classifyRoleFamily(jobDescription, jobTitle ?? '');\n const cv = classifyRoleFamily(resumeRoleText(resume));\n if (!jd || !cv) {\n return {\n id: 'role-family-match',\n tier: 'match',\n weight: 'high',\n status: 'skipped',\n score: 0,\n message: 'Could not confidently classify the role family of the JD or resume.',\n hints: [],\n };\n }\n if (jd.family !== cv.family) {\n return {\n id: 'role-family-match',\n tier: 'match',\n weight: 'high',\n status: 'fail',\n score: 0,\n message: `Role mismatch: ${cv.family} resume vs ${jd.family} role.`,\n hints: [\n `This posting reads as a ${jd.family} role; your resume reads as ${cv.family}. Likely not a fit.`,\n ],\n };\n }\n\n // Same family — for engineering, also gate on sub-specialty. A Frontend\n // Architect is not an Application Security engineer even though both are\n // \"engineering\". Only fires when the JD title/body names a clear specialty\n // the resume doesn't evidence (fullstack ↔ frontend/backend treated as ok).\n if (cv.family === 'engineering') {\n const jdSpec = classifySpecialty(jobDescription, jobTitle ?? '');\n if (jdSpec) {\n const cvTopSpecs = resumeSpecialties(resume);\n // Penalize only when the resume has clear specialties and none is the one\n // the JD demands. A general-engineering resume (no clear specialty) isn't\n // penalized — it could plausibly fit.\n const satisfied = cvTopSpecs.length === 0 || cvTopSpecs.includes(jdSpec);\n if (!satisfied) {\n return {\n id: 'role-family-match',\n tier: 'match',\n weight: 'high',\n status: 'fail',\n score: 0,\n message: `Specialty mismatch: ${jdSpec} role, resume specializes in ${cvTopSpecs[0] ?? 'general engineering'}.`,\n hints: [\n `This is a ${jdSpec} engineering role; your resume doesn't show ${jdSpec} depth. Likely not a fit.`,\n ],\n };\n }\n }\n }\n\n return {\n id: 'role-family-match',\n tier: 'match',\n weight: 'high',\n status: 'pass',\n score: 100,\n message: `Role family aligned (${cv.family}).`,\n hints: [],\n };\n};\n\nexport const allMatchChecks = [\n hardSkillOverlap,\n titleAlignment,\n roleFamilyMatch,\n educationLevel,\n yoeMatch,\n];\n\ninterface KnockoutPattern {\n signal: string;\n jdPattern: RegExp;\n resumeMatch: (r: ResumeSchema, m: RegExpMatchArray) => boolean;\n recommendation: string;\n}\n\nconst KNOCKOUTS: KnockoutPattern[] = [\n {\n signal: 'work-auth',\n jdPattern:\n /(work\\s*auth|authorization to work|right to work|us citizen|green card|h-?1b|visa sponsorship)/i,\n resumeMatch: (r) =>\n /(work auth|authorized|citizen|green card|visa)/i.test(r.basics?.summary || ''),\n recommendation: 'Confirm authorization status in the application form.',\n },\n {\n signal: 'location',\n jdPattern: /(must be located|on-?site|relocate|based in)\\s+([a-zA-Z ,]+)/i,\n resumeMatch: (r, m) => {\n const jdLoc = (m[2] ?? '').toLowerCase().trim();\n const resumeCity = (r.basics?.location?.city ?? '').toLowerCase().trim();\n if (!jdLoc || !resumeCity) return false;\n return jdLoc.includes(resumeCity) || resumeCity.includes(jdLoc.split(/[, ]+/)[0] ?? '');\n },\n recommendation: 'Verify location requirement against your basics.location.city.',\n },\n {\n signal: 'clearance',\n jdPattern: /(ts\\/sci|secret clearance|security clearance|active clearance)/i,\n resumeMatch: (r) => /clearance/i.test(JSON.stringify(r)),\n recommendation: 'Confirm clearance level on the application form.',\n },\n {\n signal: 'certification',\n jdPattern: /(cissp|aws certified|pmp|ccna|cpa|required certification)/i,\n resumeMatch: (r) => (r.certificates?.length ?? 0) > 0,\n recommendation: 'List required certificates in the certificates section if held.',\n },\n];\n\nexport function extractKnockouts(resume: ResumeSchema, jobDescription: string): KnockoutSignal[] {\n const out: KnockoutSignal[] = [];\n for (const k of KNOCKOUTS) {\n const m = jobDescription.match(k.jdPattern);\n if (!m) continue;\n if (k.resumeMatch(resume, m)) continue;\n out.push({\n signal: k.signal,\n evidence: `JD: \"${m[0]}\"; resume silent.`,\n recommendation: k.recommendation,\n });\n }\n return out;\n}\n","import type { CheckResult, AtsRating, Grade, AtsConfig } from './types';\n\nconst weightMultiplier: Record<'high' | 'medium' | 'low', number> = {\n high: 3,\n medium: 2,\n low: 1,\n};\n\nexport function gradeFromScore(score: number, t: AtsConfig['thresholds']['grade']): Grade {\n if (score >= t.A) return 'A';\n if (score >= t.B) return 'B';\n if (score >= t.C) return 'C';\n if (score >= t.D) return 'D';\n return 'F';\n}\n\nexport function computeTierScore(checks: CheckResult[]): number {\n const active = checks.filter((c) => c.status !== 'skipped');\n if (active.length === 0) return 0;\n let weighted = 0;\n let total = 0;\n for (const c of active) {\n const m = weightMultiplier[c.weight];\n weighted += c.score * m;\n total += 100 * m;\n }\n return total > 0 ? Math.round((weighted / total) * 100) : 0;\n}\n\nexport function computeTotalScore(\n tiers: { parsing: number; match?: number; recruiter: number },\n weights: AtsConfig['weights']['tiers']\n): number {\n if (tiers.match === undefined) {\n const sum = weights.parsing + weights.recruiter;\n const wp = weights.parsing / sum;\n const wr = weights.recruiter / sum;\n return Math.round(\n tiers.parsing * (sum === 50 ? 0.4 : wp) + tiers.recruiter * (sum === 50 ? 0.6 : wr)\n );\n }\n const sum = weights.parsing + weights.match + weights.recruiter;\n return Math.round(\n (tiers.parsing * weights.parsing +\n tiers.match * weights.match +\n tiers.recruiter * weights.recruiter) /\n sum\n );\n}\n\nexport function scoreToRating(score: number, t: AtsConfig['thresholds']['rating']): AtsRating {\n if (score >= t.excellent) return 'excellent';\n if (score >= t.good) return 'good';\n if (score >= t.needsWork) return 'needs-work';\n return 'poor';\n}\n\nexport function generateSummary(\n score: number,\n rating: AtsRating,\n hasJd: boolean,\n knockouts: number\n): string {\n const ratingLabel = {\n excellent: 'Excellent',\n good: 'Good',\n 'needs-work': 'Needs Work',\n poor: 'Poor',\n }[rating];\n const knockoutNote =\n knockouts > 0 ? ` ${knockouts} knockout signal${knockouts === 1 ? '' : 's'} flagged.` : '';\n return `ATS ${score}/100 (${ratingLabel}).${hasJd ? ' Includes JD match.' : ''}${knockoutNote}`;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport yaml from 'yaml';\nimport { z } from 'zod';\nimport merge from 'lodash.merge';\nimport type { AtsConfig } from '../ats/types';\n\nconst weightEnum = z.enum(['high', 'medium', 'low']);\n\nconst atsConfigSchema = z.object({\n weights: z\n .object({\n tiers: z\n .object({\n parsing: z.number().int().min(0).max(100),\n match: z.number().int().min(0).max(100),\n recruiter: z.number().int().min(0).max(100),\n })\n .partial()\n .optional(),\n checks: z.record(z.string(), weightEnum).optional(),\n })\n .partial()\n .optional(),\n thresholds: z\n .object({\n rating: z\n .object({\n excellent: z.number(),\n good: z.number(),\n needsWork: z.number(),\n })\n .partial()\n .optional(),\n grade: z\n .object({ A: z.number(), B: z.number(), C: z.number(), D: z.number() })\n .partial()\n .optional(),\n seniorYoeCutoff: z.number().int().min(0).optional(),\n wordCount: z\n .object({ min: z.number(), max: z.number(), seniorMax: z.number() })\n .partial()\n .optional(),\n bulletsPerRole: z\n .object({ min: z.number(), max: z.number(), seniorMax: z.number() })\n .partial()\n .optional(),\n })\n .partial()\n .optional(),\n disable: z.array(z.string()).optional(),\n locale: z.string().optional(),\n});\n\nconst fileSchema = z.object({ ats: atsConfigSchema.optional() });\n\nexport const defaultConfig: AtsConfig = {\n weights: {\n tiers: { parsing: 30, match: 50, recruiter: 20 },\n checks: {},\n },\n thresholds: {\n rating: { excellent: 90, good: 75, needsWork: 60 },\n grade: { A: 90, B: 80, C: 70, D: 60 },\n seniorYoeCutoff: 10,\n wordCount: { min: 400, max: 800, seniorMax: 1600 },\n bulletsPerRole: { min: 3, max: 6, seniorMax: 10 },\n },\n disable: [],\n locale: 'en',\n};\n\nexport interface LoadConfigOptions {\n cwd?: string;\n configPath?: string;\n}\n\nexport function loadConfig(opts: LoadConfigOptions = {}): AtsConfig {\n const cwd = opts.cwd ?? process.cwd();\n const file = opts.configPath ?? path.join(cwd, 'resuml.config.yaml');\n if (!fs.existsSync(file)) return defaultConfig;\n\n const raw = fs.readFileSync(file, 'utf8');\n const parsed = (yaml.parse(raw) as unknown) ?? {};\n const result = fileSchema.safeParse(parsed);\n if (!result.success) {\n const issue = result.error.issues[0];\n const where = issue?.path.join('.') ?? '<root>';\n throw new Error(`Invalid resuml.config.yaml at \"${where}\": ${issue?.message}`);\n }\n return merge({}, defaultConfig, result.data.ats ?? {});\n}\n\nexport function effectiveWeight(\n checkId: string,\n defaultWeight: 'high' | 'medium' | 'low',\n config: AtsConfig\n): 'high' | 'medium' | 'low' {\n return config.weights.checks[checkId] ?? defaultWeight;\n}\n","import type { ResumeSchema } from '../types/resume';\nimport type {\n TieredAtsResult,\n AtsOptions,\n CheckResult,\n TierResult,\n Tier,\n AtsConfig,\n KnockoutSignal,\n} from './types';\nimport { allParsingChecks } from './checks/parsing';\nimport { allRecruiterChecks } from './checks/recruiter';\nimport { allMatchChecks, extractKnockouts } from './checks/match';\nimport {\n computeTierScore,\n computeTotalScore,\n gradeFromScore,\n scoreToRating,\n generateSummary,\n} from './scoring';\nimport { defaultConfig, effectiveWeight } from '../utils/config';\n\nfunction applyConfig(checks: CheckResult[], cfg: AtsConfig): CheckResult[] {\n return checks\n .filter((c) => !cfg.disable.includes(c.id))\n .map((c) => ({ ...c, weight: effectiveWeight(c.id, c.weight, cfg) }));\n}\n\nfunction buildTier(_tier: Tier, checks: CheckResult[], cfg: AtsConfig): TierResult {\n const filtered = applyConfig(checks, cfg);\n const score = computeTierScore(filtered);\n return {\n score,\n grade: gradeFromScore(score, cfg.thresholds.grade),\n checks: filtered,\n };\n}\n\nexport function analyzeAts(resume: ResumeSchema, options: AtsOptions = {}): TieredAtsResult {\n const cfg = options.config ?? defaultConfig;\n const language = options.language ?? cfg.locale;\n\n const parsingChecks = allParsingChecks.map((fn) => fn(resume, language));\n\n const recruiterChecks = allRecruiterChecks.map((fn) => fn(resume, language, cfg));\n\n const parsing = buildTier('parsing', parsingChecks, cfg);\n const recruiter = buildTier('recruiter', recruiterChecks, cfg);\n\n let match: TierResult | undefined;\n let knockouts: KnockoutSignal[] = [];\n let roleMismatch = false;\n if (options.jobDescription) {\n const matchChecks = allMatchChecks.map((fn) =>\n fn(resume, language, { jobDescription: options.jobDescription, jobTitle: options.jobTitle })\n );\n match = buildTier('match', matchChecks, cfg);\n roleMismatch = matchChecks.some(\n (c) => c.id === 'role-family-match' && c.status === 'fail'\n );\n knockouts = extractKnockouts(resume, options.jobDescription);\n }\n\n let totalScore = computeTotalScore(\n { parsing: parsing.score, match: match?.score, recruiter: recruiter.score },\n cfg.weights.tiers\n );\n\n // A confident occupation mismatch is decisive: resume hygiene (parsing +\n // recruiter tiers, ~50% of the weight by default) cannot lift a wrong-role\n // posting into a passing score. Cap it so the total reflects fit, not polish.\n const capped = roleMismatch && totalScore > ROLE_MISMATCH_CAP;\n if (capped) totalScore = ROLE_MISMATCH_CAP;\n\n const rating = scoreToRating(totalScore, cfg.thresholds.rating);\n let summary = generateSummary(totalScore, rating, !!options.jobDescription, knockouts.length);\n if (capped) summary += ' Score capped: resume role family does not match this posting.';\n\n return {\n score: totalScore,\n rating,\n tiers: match ? { parsing, match, recruiter } : { parsing, recruiter },\n knockouts,\n summary,\n };\n}\n\n/** Ceiling applied to the total when the resume and JD are different occupations. */\nconst ROLE_MISMATCH_CAP = 45;\n\nexport type { TieredAtsResult, AtsOptions, CheckResult, TierResult, KnockoutSignal } from './types';\n"],"mappings":"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A;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC3JA,IAAM,KAAmB;AAAA,EACvB,aAAa;AAAA;AAAA,IAEX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU,CAAC,KAAK,MAAM,MAAM,QAAQ,UAAU,MAAM,OAAO,MAAM;AAAA,EACjE,WAAW;AAAA;AAAA,IAET;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAO,aAAQ;;;AChrBf,IAAM,KAAmB;AAAA,EACvB,aAAa;AAAA;AAAA,IAEX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,I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","names":["sum"]}
|