diff --git a/lib/filter.mjs b/lib/filter.mjs index 76c4346..856b721 100644 --- a/lib/filter.mjs +++ b/lib/filter.mjs @@ -19,53 +19,22 @@ export function loadProfile(profilePath) { } function buildSystemPrompt(jobProfile, candidateProfile) { - const tr = jobProfile.target_role; - const exp = jobProfile.experience || {}; - const highlights = (exp.highlights || []).map(h => `- ${h}`).join('\n'); + return `You are a job relevance scorer. Score each job listing 0-10 based on how well it matches the candidate profile below. - return `You are a job relevance scorer. Score each job 0-10 based on how well it matches this candidate. +## Candidate Profile +${JSON.stringify(candidateProfile, null, 2)} -## Candidate -- Name: ${candidateProfile.name?.first} ${candidateProfile.name?.last} -- Location: ${candidateProfile.location?.city}, ${candidateProfile.location?.state} (remote only, will not relocate) -- Years in sales: ${candidateProfile.years_experience} -- Desired salary: $${(candidateProfile.desired_salary || 0).toLocaleString()} -- Background: ${(candidateProfile.cover_letter || '').substring(0, 300)} +## Target Job Profile +${JSON.stringify(jobProfile, null, 2)} -## Target Role Criteria -- Titles: ${(tr.titles || []).join(', ')} -- Industries: ${(exp.industries || []).join(', ')} -- Company stage: ${(tr.company_stage || []).join(', ') || 'any'} -- Company size: ${tr.company_size || 'any'} -- Salary minimum: $${(tr.salary_min || 0).toLocaleString()} -- Remote only: ${tr.remote ? 'Yes' : 'No'} -- Excluded keywords: ${(tr.exclude_keywords || []).join(', ')} +## Instructions +- Use the candidate profile and target job profile above as your only criteria +- Score based on title fit, industry fit, experience match, salary range, location/remote requirements, and any exclude_keywords +- 10 = perfect match, 0 = completely irrelevant +- If salary is unknown, do not penalize +- If a posting is from a staffing agency but the role itself matches, score the role — not the agency -## Experience Highlights -${highlights} - -## Scoring Guide -10 = Perfect match (exact title, right company stage, right industry, right salary range) -7-9 = Strong match (right role type, maybe slightly off industry or stage) -5-6 = Borderline (relevant but some mismatches — wrong industry, seniority, or vague posting) -3-4 = Weak match (mostly off target but some overlap) -0-2 = Not relevant (wrong role type, wrong industry, recruiter spam, part-time, etc.) - -Penalize heavily for: -- Part-time roles -- Wrong industry (insurance, healthcare PR, construction, retail, K-12 education, utilities) -- Wrong role type (SDR/BDR, customer success, partnerships, marketing, coordinator) -- Junior or entry-level positions -- Staffing agency posts with NO discernible real role or company (pure spam) — if the role and responsibilities are clearly described, DO NOT penalize for being posted by a recruiter/agency -- Salary clearly below minimum -- Geographic mismatch (non-remote, requires relocation) - -Do NOT penalize for: -- Company size or funding stage (this is an enterprise AE role — large companies are fine) -- SMB or mid-market segments (these are valid AE roles) -- Staffing agency postings where the actual role is clearly described - -Return ONLY a JSON object: {"score": <0-10>, "reason": ""}`; +Return ONLY a JSON object: {"score": <0-10>, "reason": ""}`; } function sanitize(str) {