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
135 lines
11 KiB
Markdown
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.
|