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

135 lines
11 KiB
Markdown

# Scout UI — Lean Finalization Spec
> Screen-by-screen "what we surface" decisions for the Scout UI, made against what the **engine +
> deployed agents can actually produce** (see `ENGINE_DESIGN.md`, `SIGNAL_AUDIT_V2.md`,
> `agent-capability` evidence). Work happens **in-place in `dashboard-ui/scout`** (no rebuilds).
> Written 2026-06-16.
## Guiding principles
- **Don't fake it; lock it.** Features that are real *later* are shown as a tasteful **"coming soon"
locked tile**, never with fabricated data. Nothing here is a lie.
- **Personas stay only where backed.** **Mira** = real (resume-builder parsed/tailored an existing
résumé) → keep. The bubble-journey **"Nova"** is being replaced wholesale (see Configure) → gone.
- Cut the three never-backed claims everywhere: **"live status", "in-network", invented deadlines.**
---
## Summary tab (two states)
### First-time view → **UNCHANGED**
Onboarding doorway (hero + 4-step "how it works" + CTA). Locked as-is — "812 live roles" reads as
*market scale*, not a corpus claim; "Mira" is backed. No edits.
### Returning view (metrics dashboard) → leaned
- **KEEP (producible today):** Streak · Monthly report · Readiness·QX (qscore + assessment) ·
Matches found · Top match · Salary band · Competition (avg applicants from listings) · Match range/
distribution · Momentum / Readiness trend (qscore over time) · What your agents did (logged) ·
**Application funnel** = `Matches → Viewed → Shortlisted → Applied`, **all user-activity** (Viewed =
jobs the user opened, Shortlisted = saved) · **Your Apply window** (freshness-based urgency from
listing posting-age, replaces generic "Golden window") · **Your rank** = activity percentile from
**Scout activity only** (searches/views/saves/applies in the matchmaking DB; "top X% by how much
you're working your search" — honest engagement, not a quality claim) · Search stage.
- **🔒 LOCK (coming soon):** Expert / human review.
- **CUT:** Search plan ("as you sleep") · Proof-ready · Market value · Response·tracked (no recruiter
callback) · Warm intros (no referral agent).
---
## Configure tab → ~90% intact (the strongest screen)
| Section | Decision |
|---|---|
| Hero "Here's the search I'd run for you" | ✅ keep |
| Profile summary ("parsed by **Mira**", title/seniority/industry/city/years) | ✅ keep — real (resume-builder + LinkedIn) |
| **"Matching you on N signals"** transparency bar | ✅ keep, **but fix the list** to match `SIGNAL_AUDIT_V2`: keep Role&level + Skills + What-you-value; **Market context is now BACKED via Perplexity** (keep); add verified-LinkedIn / QScore / course-behavior; drop any item with no source |
| "Also matching on · derived" (comp/stage/availability/deal-breakers/dream cos/hide-employer) | ✅ keep — real preference/filter inputs |
| **Video intro** | ✅ **KEEP** — reuse the existing `VideoResumeBuilder.tsx`; persist via interview-service's MinIO blob storage (record → store). Drop the "rides with in-network" copy |
| "What are you after?" (More like this / step up / new) | ✅ keep — **FIT vs STRETCH** core |
| "What matters most?" (pick 2) | ✅ keep — ranking weights |
| "How far should I reach?" (Safe/Balanced/Reach) | ✅ keep — reach band |
| "Work mode" | ✅ keep — hard filter |
| **The must-haves bubble box** ("Fine-tune everything") | ✅ **KEEP the box, swap the engine** → reuse course **`BubblePicker` + `useBubbleField`** (physics: grow-on-like +6 / love +12, live repack). **"Add your own" on EVERY row (crucial)** — esp. **Where/location** (tier-2/3 cities typed → real preferred-location bubble). **AI suggestions via `onGenerateMore` but STRIP the "ai" badge** — untagged, indistinguishable from presets. Replaces `ScoutBubbleJourney`/Nova |
| **Location** (the "Where" row, lives in the bubble box) | ✅ feeds the **ported location-fit logic** (`SIGNAL_AUDIT_V2`): substring city match, Remote→100, Anywhere→open. Add-your-own + that scoring = location finally handled right |
| Footer "Scout never applies without you" | ✅ keep — honest consent |
**Net Configure:** keep almost everything; the only real changes are (1) fix the signal-transparency
list to the true set, (2) reuse `VideoResumeBuilder` for video-intro, (3) replace the bubble journey
with the course bubbler (add-your-own + untagged AI), (4) wire the ported location logic.
---
## Action tab → leaned, with an honest apply flow
**A) Loader** (`JobMatchingLoader`) — **rework copy to the on-demand truth:** *"Looking in 3+ job
boards · Scanning 100+ roles"* → normalize skills → score against your signals → rank. Drop the fake
"812 corpus scan." ("fresh by construction — pulled seconds ago.")
**B) Filter bar** — ✅ keep (the hard filters + active chips + Clear all).
**C) Match card** (`MatchCard`):
| Element | Decision |
|---|---|
| match % + **QX breakdown** | ✅ keep — but it IS **the engine's match breakdown**: the white-box signal dimensions (skill match, experience, **location-fit**, course-behavior, QScore competence, market context). "Why we matched you," powered by the real engine, not gamified QX |
| title · ₹pay · applicants | ✅ keep (from listings) |
| **"Closes in N days"** | ❌ **removed** → "posted Nd ago" (no real deadline data) |
| "+N QX on apply" · "Proof-ready" · "In-network · live status" | ❌ cut |
| "Video intro ✓" | ✅ keep (reuse Video Resume; drop in-network gating) |
| "Warm intro · can refer you" | ❌ cut (no mentor/referral agent) |
| "light on {gap} → 15-min mock / Expert mock / {course}" | ✅ keep (interview/roleplay/course are real) |
| "Why Scout picked this" + tags | ✅ keep — wire to the TRUE signals |
**D) Swipe controls** (Pass / undo / info / Save) — ✅ keep. These emit the **VIEW / SAVE / PASS
events** that feed the funnel + activity rank.
**E) Apply flow (the hand-off) — make it honest and concrete:**
1. **Approve once** — the single consent tap (keep).
2. **Per-job résumé tailoring** — for each saved role, resume-builder tailors the résumé + cover
letter. **NEW UX: a per-job spinner** ("Tailoring your résumé for {company}…") — this step had no UI.
3. **Auto-apply** — the master-key engine submits (tier-aware: public-ATS/India-ATS = autonomous;
login-gated = staged handoff).
4. **Result — split, with proof:**
-**Applied (auto):** show the **captured confirmation screenshot** per role — *verified, not
assumed* (the engine already screenshots the success page).
- ⚠️ **Couldn't auto-apply** (login_required / no_form / failed / spam-flagged): list these with
**"Apply manually →"** + the live link, so the user finishes them by hand.
**Net Action:** real bones kept (match + engine breakdown + why + mock/course boosts + apply), the
recurring cuts applied (in-network/live-status, +QX framing, warm-intro/referral, add-to-pathway,
deadlines), loader made honest, and the apply flow gains the **resume-tailoring spinner** + **proof
screenshots** + **manual-apply fallback** for failures.
---
## BUILD PROGRESS — as shipped on branch `job-ui-final` (updated 2026-06-17)
Built in-place in `dashboard-ui/scout` (+ `components/job-matching`). Committed/pushed:
`job-ui-final` (head `780e09e`+). All states compile; `/scout` serves clean. The build went
**further than this spec in places** — recorded here so the spec stays the source of truth.
Honesty check: **every divergence is a cut or an improvement; nothing surfaces a claim the engine
can't back** (re-verified against `ENGINE_DESIGN.md`).
**Configure (most changed):**
- ✅ Bubble box swapped to the ported course physics — `components/scout/bubble/{useBubbleField,ScoutBubbleField}`; like/love grow+repack, **add-your-own + untagged "Suggest more"** on taste rows. (`ScoutBubbleJourney` rewired off Nova/`NovaBubbles`.)
- ✅ Location upgraded **beyond spec**: cascading **Country→City** picker (`LocationPicker.tsx`, ported from the old matchmaking `FilterBar` — flags, searchable city, "select country first"). Stored as `"City · Country"`; the deck matcher now scores **city AND country** (`filterSortScoutJobs`). Feeds Tier-A `preferred_locations`.
- ✅ Profile card is now **editable in place** ("Edit details" ↔ "Done") + a **"Fine-tune" orange pill** (header) and **"Fine-tune everything"** (bottom) → the bubble journey. All dropdowns are one shared **searchable `CustomSelect`** (type-your-own → "Use 'X'") with an **"Any"** option that maps to *no constraint* for the engine.
-**No-resume / nothing-selected state** (NEW, not in original spec): card opens in edit mode, every field defaults to **"Any"**, headline "What are you looking for?", an **"Add a resume to pre-fill"** action (simulated Mira parse). This is the UI face of engine §3.3 (sparse profile → coverage renormalizes, never fabricates). Preview toggle to view both states.
- ⚠️ **DIVERGENCE — "Matching you on N signals" bar: REMOVED** (text-light pass), not "kept + fixed" as spec said. Signals still feed the engine; just not surfaced. *Re-add a 1-line honest version if we want the credibility back.*
- ⚠️ **DIVERGENCE — Video intro: REMOVED** from card + chip (Tier-C, not wired). Spec wanted keep.
- ⚠️ **DIVERGENCE — dream-companies + hide-employer editing dropped** (kept comp/stage/availability/deal-breakers as read-only chips → editable inline).
- ✅ Removed the lame **"Use my résumé instead"** shortcut everywhere.
**Summary:**
- ✅ 9 headline cards (activity-led) + 3 behind "More metrics"; Expert/human review **locked "coming soon"** (Mira/Vera hand-offs stay live).
- ✅ Market signals trimmed to producible set (dropped layoff/funnel/hiring-velocity).
- ⚠️ **DIVERGENCE — Readiness·QX assessment card REMOVED** (+8 QX reward theatre gone). QScore/assessment remain real Tier-B engine signals; "Readiness trend" still in More-metrics. Spec wanted keep.
- ⚠️ **PENDING — "Golden apply window" not yet renamed** to the freshness/posting-age "Apply window" (§6.1).
**Action / match:**
- ✅ Loader honest: `Looking across 3+ job boards · Scanning 100+ live roles · Scoring · Ranking`; **MATCH_SCOPE 812→120**.
-**Video-intro chip removed** from `MatchCard`.
- ✅ Swipe card **action-bar overlap fixed** — card now renders in normal flow (`AnimatePresence popLayout`), so expanding the QX breakdown grows the page and Pass/Undo/Info/Save stay below it (removed the brittle absolute+ResizeObserver container).
- ⚠️ **DIVERGENCE — Action-tab filter bar + chips + `ScoutFilterSheet`: REMOVED.** Configure is the single source of search criteria; empty deck → "Adjust in Configure". Spec wanted keep.
- 🔧 **PENDING (needs engine):** apply-flow proof screenshots + auto/failed→manual split; per-job resume-tailoring spinner. These wait on engine apply-result statuses.
**Text/polish:** all accented "résumé" → plain **"resume"**; "Pick 2" casing.