Files
matchmaking-v2/research/docs/ENGINE_INPUTS.md
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

12 KiB
Raw Permalink Blame History

Scout → Engine — Exhaustive Input Inventory

Every field the new Scout UI (dashboard-ui, branch job-ui-final) produces that is (or should be) an input to matchmaking-v2. Derived field-by-field from the code, cross-checked against what the handlers actually pass (ScoutConfirm.go(), ScoutBubbleJourney.toPrefs()). Written 2026-06-17. Pair with ENGINE_DESIGN.md §2 (signal tiers) and SIGNAL_AUDIT_V2.md.

There are three kinds of input:

  1. Search prefs — the ScoutPrefs object the UI hands the engine per search (onDone(prefs)).
  2. Profile/context — assembled by the orchestrator context_resolver (resume + LinkedIn + QScore + course-behavior); NOT picked in Scout, but the Confirm card displays/edits some of it.
  3. Behavioral events — view/save/pass emitted while swiping (learning loop + activity rank).

1. SEARCH PREFS — the ScoutPrefs contract (what onDone sends)

# Field Type UI surface(s) Options / shape Engine role (per ENGINE_DESIGN §2/§3)
1 role string[] Bubble journey role stage (like/love); Confirm via intent Product/Design/Engineering/Data/Marketing/Sales/Ops/Open-to-any + add-your-own Tier-A target_rolesfilter, not score (want, not is)
2 industry string[] Confirm "Industry" select; Bubble journey industry stage Fintech/SaaS/E-commerce/EdTech/HealthTech/Dev tools/Consulting + Any + add-your-own Tier-A target_industries — filter
3 location string[] Confirm "Where" (LocationPicker); Bubble constraints (LocationPicker) "City · Country" strings (+ Remote/Anywhere) — cascading Country→City + custom Tier-A preferred_locationshard filter + location-fit (city AND country substring; Remote→100; Anywhere→open)
4 workMode string[] Confirm "Work mode"; Bubble constraints Remote/Hybrid/On-site (Any = none) Tier-A work mode — hard filter
5 experience string[] Confirm "Seniority" select; Bubble constraints Fresher/Junior/Mid-level/Senior/Lead + Any Tier-A seniority floor — hard filter
6 targetComp string? Confirm "Target comp" select ₹1014L … ₹30L+ + Any preference signal (NOT self-declared salary, which §2 discards; this is target band)
7 companyStage string? Confirm "Company stage" select Seed/Growth/Late-pre-IPO/Enterprise + Any company-fit enricher
8 availability string? Confirm "Availability" select Open now / 30d / 6090d / Just exploring + Any timing context
9 dealBreakers string[]? Confirm "Deal-breakers" chips Remote-first/No on-call/Equity/Visa/4-day/No relocation hard exclusions
10 priorities string[]? Confirm "What matters most? · Pick 2" up to 2 of PRIORITY_OPTIONS ranking weights (soft — orders results)
11 stretch Stretch? Confirm "How far should I reach?" safe / balanced / reach FIT↔STRETCH reach band (§3.5) → match-score floor
12 sort "match"|"salary"|"closing" default "match"; Shortlist has a local sort output ordering (not a match signal)
13 intent (not stored on prefs; shapes 1/2/5) "same"|"levelup"|"new" Confirm "What are you after?" More like this / A step up / Something new FIT vs STRETCH selector (§3.5) — current-state vs aspiration
14 title wired 2026-06-17 string? Confirm card "Title" input free text Tier-A current_role / title (filter + weight). Sole title source when no resume
15 years wired 2026-06-17 number? Confirm card "Experience (yrs)" input number Tier-A years_experience (weight). Sole years source when no resume
16 targetTitles added 2026-06-17 string[] (single-select → ≤1) Bubble journey stage 3 "Roles that fit you" — AI/resume+LinkedIn-generated specific titles, pick one e.g. "Payments PM", "Risk & Fraud Product" High-signal Tier-A target — the precise role the engine should prefer to seed the on-demand board query (specific > broad role). The "true fine-tuning" pick. Generation is a STUB for the GPT-5.4 /suggest call, mirroring the courses AI flow.

Both title and years flow through both paths — ScoutConfirm.buildPrefs() and (via the carry-forward base) ScoutBubbleJourney.toPrefs(), so Fine-tune no longer drops them.


2. ⚠️ Remaining gap — captured but not fully used

Field Where it's collected Status Why it matters
bubble like vs love Bubble journey (3-state) FlattenedtoPrefs() maps both → "selected" "love" = top priority — a free weight signal still collapsed to binary. Optional: feed a per-pick weight

Resolved 2026-06-17: the bubble-journey path (toPrefs) used to drop everything except role/industry/workMode/experience/location. It now starts from the carry-forward base the Confirm card passes in, so title/years/comp/stage/availability/deal-breakers/priorities/stretch survive Fine-tune.


3. RESOLVED — orphaned prefs DROPPED from the contract (2026-06-17)

These had no UI surface left, so they were removed from ScoutPrefs entirely (interface, emptyPrefs, resumePrefs, filterSortScoutJobs, go()), and the orphaned ScoutFilterSheet.tsx + its option constants (JOB_TYPE_OPTIONS, SALARY_BANDS, JOB_TYPE_TO_VALUE, DREAM_COMPANY_OPTIONS) were deleted.

Field Was Now
jobType Action filter sheet (removed) dropped
salaryBand Action filter sheet (removed) dropped (targetComp is the surviving comp input)
dreamCompanies Confirm card edit (cut) dropped
hideEmployer Confirm card toggle (cut) dropped

4. BEHAVIORAL EVENTS — emitted while swiping (feed the learning loop, not the per-search query)

Event UI trigger Engine role
VIEW open a card / tap info (expand QX breakdown) funnel "Viewed"; activity rank; weak relevance label
SAVE swipe right / Save (heart) funnel "Shortlisted"; strong positive label (§3.1 ⑥ accrue save/apply → learned ranker)
PASS swipe left / X negative label
UNDO undo button corrects the last save/pass
APPLY (hand-off) DeckEnd "approve once" → auto/manual apply un-gameable ground truth (§4) — the real save/apply rate

5. PROFILE / CONTEXT — assembled by context_resolver, surfaced (not picked) in Scout

The Confirm card displays and lets you edit the resume-derived defaults; the rest is read server-side. A no-resume user sends all of §1 as "Any"/open → engine §3.3 coverage-renormalizes (never fabricates).

Source Fields Tier
Resume (resume-builder parse, "Mira") title, seniority, industry, city, years, + pre-filled guesses for comp/stage/availability/deal-breakers/priorities/stretch (editable on the card) A / B
LinkedIn (social-branding, live fetch) verified title / company / industry; education; certifications B
QScore 10-D quotient vector (already digests interview + roleplay) B
Assessment passed / percentage (user-service) B
Course watch-behavior (growqr_course) revealed-preference booster (e.g. completes React → frontend signal) C (additive)
Interview / roleplay rubrics 8-D / 6-D (low coverage) C (additive) — read later only if lift beyond QScore

6. DEEP AUDIT — every engine signal × frontend coverage (2026-06-17)

Walks the entire SIGNAL_AUDIT_V2.md inventory (Tier A/B/C + labels) and assigns each signal an owner. Rule: the frontend owns only what the user states (request prefs + editable overrides + feedback events). Everything resume/identity/competence-derived is server-assembled by context_resolver / qscore / Perplexity / growqr_course — by design NOT a Scout UI field.

Engine signal (SIGNAL_AUDIT_V2) Owner Frontend field / event Status
Tier A
years_experience Frontend override + resume years (Confirm) WIRED (was the gap)
current_role / title Frontend override + resume/LinkedIn title (Confirm) WIRED (was the gap)
skills → ESCO Server (resume parse) — (not a Scout pref) correctly server-side
preferred_locations + work mode Frontend (request prefs) location (City·Country), workMode WIRED
target_roles / target_industries Frontend (request prefs) role, industry WIRED
Tier B
verified title / company / industry Server (social-branding LinkedIn) industry/title overridable via Confirm server; overrides wired
degree / field / institution Server (resume/LinkedIn) server-side
certifications Server (resume/LinkedIn) server-side
assessment scores Server (user-service) server-side
QScore quotient vector (10-D) Server (qscore-service) server-side
market context (demand/freshness/comp) Server (Perplexity, cached) server-side
Tier C (additive boosters)
course watch-behavior Server (growqr_course) server-side
improvement velocity / coachability Server (interview/roleplay) server-side
video on-camera presence Server (interview/roleplay) server-side
Soft ranking / FIT-STRETCH (engine §3.4/§3.5)
ranking weights Frontend priorities (Pick 2) WIRED
reach band Frontend stretch WIRED
FIT vs STRETCH selector Frontend intent WIRED
comp / stage / availability / deal-breakers Frontend targetComp/companyStage/availability/dealBreakers WIRED
Labels (training targets)
SAVE / DISMISS / APPLY feedback Frontend events swipe deck + apply hand-off emitted (§4)

Verdict

Every engine input the frontend is responsible for is now wired. After this pass there are no dropped frontend fieldstitle + years were the last gaps and are now sent on both paths. Everything still "unwired" in the UI is server-assembled context (skills, LinkedIn identity, QScore, assessment, course-behavior, market context) and must not be a Scout form field — capturing it client-side would duplicate or fake what context_resolver already assembles.

Only non-blocking residual: the bubble like vs love 3-state is flattened to binary "selected" (toPrefs); wiring it as a per-pick weight is an optional enhancement, not a missing engine input.


Summary — counts

  • 15 search-pref fields actively sent (incl. intent). The ScoutPrefs contract is now exactly: role · location · workMode · experience · industry · sort · title · years · targetComp · companyStage · availability · dealBreakers · priorities · stretch (+ intent shapes role/industry/experience).
  • title + years WIRED (2026-06-17) on both the Confirm and Fine-tune paths — were the last gaps.
  • 1 non-blocking residual (bubble like/love → binary) — optional weight enhancement, not a missing input.
  • 4 orphaned prefs DROPPED (jobType, salaryBand, dreamCompanies, hideEmployer) — contract trimmed to only what the UI renders.
  • 5 behavioral events for the learning loop.
  • 6 server-assembled context sources (skills/LinkedIn/QScore/assessment/course-behavior/market) — correctly NOT Scout fields.
  • Deep-audit verdict (§6): every frontend-owned engine input is wired; no dropped fields remain.