Files
raulgupta 89ca9ad647 Initial commit: matchmaking-v2 on-demand multi-board job-search agent
On-demand Scout service (replaces the nightly aggregator):
- FastAPI agent-mesh service; card name "matchmaking-service" (HTTP /a2a/tasks
  + Redis-stream worker matching the sibling-service pattern)
- run_search: parallel multi-board sweep (Naukri/blackfalcondata + Foundit +
  LinkedIn), city-filtered at the board, cheapest-per-result first
- per-board adapters + normalizers -> ScoutJob with rich read-only details and
  offsite apply links; recall mode + MVQ guard
- result cache for dev replay ($0); per-board cost knobs; retry-on-5xx
- research/: engine design, board cost economics, India-actor shortlist, POC
2026-06-18 19:22:03 +05:30

52 lines
2.3 KiB
Python

"""
candidate.py — the board-agnostic candidate model (used by every adapter).
= parsed résumé (source of truth) + confirmed facts not on the résumé (the "answer bank") +
the rule for writing a tailored motivation. This never changes per board — it's the user's data.
Grow CONFIRMED over time as new screening questions get answered (the answer-bank flywheel).
"""
from __future__ import annotations
import json
from datetime import date, timedelta
from parse_resume import parse_resume_to_profile
from browser_config import RESUME_PATH
# Durable answers that aren't on a résumé. Extend as new questions recur.
CONFIRMED = {
"preferred_email": "rahul.gupta2608@yahoo.com",
"citizenship": "Indian citizen, based in India",
"work_auth": ("Authorized to work in India. NOT authorized to work in the US; would require "
"visa sponsorship for any US-based role."),
"availability": "Available to start soon (within ~2 weeks).",
}
async def build_candidate(pdf_path: str = RESUME_PATH) -> dict:
profile = await parse_resume_to_profile(pdf_path)
return {"profile": profile, "facts": CONFIRMED, "resume_path": pdf_path}
def candidate_prompt_block(cand: dict) -> str:
today = date.today()
soon = today + timedelta(days=14)
f = cand["facts"]
return f"""CANDIDATE PROFILE (parsed from résumé — source of truth):
{json.dumps(cand["profile"], indent=2, ensure_ascii=False)}
CONFIRMED FACTS (override any résumé guess):
- Preferred contact email: {f["preferred_email"]}
- {f["citizenship"]}. {f["work_auth"]}
* "authorized to work where the job is located?" -> YES if the role is in India, NO if US.
* "require visa sponsorship?" -> NO if India role, YES if US role.
Honesty over optimism — never overstate authorization.
- {f["availability"]} Today is {today:%Y-%m-%d}; for a start-date picker choose a FUTURE date near
{soon:%Y-%m-%d}, never a past date.
- MOTIVATION: for any "why this role" / "about you" / "additional information" free-text field,
write a genuine 2-4 sentence answer TAILORED to THIS specific job (use its title / company /
description visible on screen) grounded in the candidate's real background above. NEVER leave it
blank — a blank motivation makes a weak application.
Résumé file to upload when asked: {cand["resume_path"]}"""