--- estimated_steps: 4 estimated_files: 3 skills_used: - best-practices - test --- # T01: Add a job-aware Gmail matching contract and backend ranking tests **Slice:** S01 — Smarter Gmail import and matching **Milestone:** M001 ## Description Build the backend contract that makes Gmail import job-aware. The executor should keep the existing OAuth flow, but add a new job-scoped candidate discovery path that uses the actual `JobApplication`, `Company`, recruiter, and existing correspondence data to rank likely Gmail messages/threads for one job. This task closes the main risk in R002 and anchors the import loop on the imported job from R001 instead of a generic inbox search. ## Steps 1. Inspect the current Gmail controller/service contract and define a job-scoped candidate response shape in `JobTrackerApi/Controllers/GmailController.cs` that includes ranked thread/message suggestions, match reasons, confidence or score inputs, and already-imported state. 2. Implement the backend matching flow in `JobTrackerApi/Controllers/GmailController.cs` and `JobTrackerApi/Services/GmailOAuthService.cs`: load the owned job with company context, derive multiple Gmail queries from recruiter/company/title/correspondence signals, fetch/dedupe results, group by thread, and rank them server-side. 3. Preserve the existing generic Gmail endpoints, but make the new job-aware endpoint the primary contract for this slice so the UI can consume it without recreating ranking heuristics in the browser. 4. Expand `JobTrackerApi.Tests/GmailControllerTests.cs` to cover owned-job lookup, empty/duplicate behavior, and ranked candidate output with explicit reasons instead of only the current missing-message-ids case. ## Must-Haves - [ ] The new backend contract is scoped to one owned `JobApplication` and never bypasses the EF ownership filters already enforced in `Data/JobTrackerContext.cs`. - [ ] Ranked candidates include enough detail for the UI to explain why a message or thread was suggested and whether it was already imported. - [ ] Tests assert the new contract and failure/duplicate cases, not just the happy path. ## Verification - `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests` - Confirm the updated tests cover job-scoped matching, duplicate flags, and invalid or missing job inputs. ## Observability Impact - Signals added/changed: per-candidate match reasons/score inputs and explicit already-imported flags in the job-scoped Gmail response. - How a future agent inspects this: hit the job-aware Gmail endpoint in `JobTrackerApi/Controllers/GmailController.cs` or read the focused assertions in `JobTrackerApi.Tests/GmailControllerTests.cs`. - Failure state exposed: the response or tests should make it obvious whether failure came from job lookup, Gmail candidate retrieval, or ranking/dedupe. ## Inputs - `JobTrackerApi/Controllers/GmailController.cs` — existing Gmail API surface and import behavior. - `JobTrackerApi/Services/GmailOAuthService.cs` — existing Gmail list/detail retrieval and current N+1 summary hydration. - `JobTrackerApi.Tests/GmailControllerTests.cs` — current minimal Gmail controller test coverage. ## Expected Output - `JobTrackerApi/Controllers/GmailController.cs` — adds the job-scoped Gmail matching endpoint and ranking contract. - `JobTrackerApi/Services/GmailOAuthService.cs` — supports the new candidate discovery flow. - `JobTrackerApi.Tests/GmailControllerTests.cs` — proves the new backend matching behavior and duplicate/failure paths.