chore(M001/S01): auto-commit after plan-slice

This commit is contained in:
2026-03-24 12:14:31 +01:00
parent c34b45dde3
commit 5ee30e3ab5
6 changed files with 81 additions and 151 deletions
@@ -1,52 +1,54 @@
---
estimated_steps: 4
estimated_files: 3
estimated_files: 4
skills_used:
- best-practices
- aspnet-core
- test
---
# T01: Add a job-aware Gmail matching contract and backend ranking tests
# T01: Add linked Gmail thread refresh to the backend contract
**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.
Finish the backend half of S01 by making already-imported Gmail threads refreshable for a single job. The executor should build on the existing job-aware matching/import flow already present in `GmailController`, keep the scope bounded to known linked thread ids, and return a clear refresh result that distinguishes new imports from duplicate-only refreshes and disconnected/failure states.
## 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.
1. Inspect the current Gmail import code in `JobTrackerApi/Controllers/GmailController.cs`, the Gmail API wrapper in `JobTrackerApi/Services/GmailOAuthService.cs`, and the current `GmailControllerTests` coverage to identify the smallest thread-refresh contract that can satisfy R002.
2. Add a job-scoped linked-thread refresh path in `JobTrackerApi/Controllers/GmailController.cs` that loads one owned job, gathers distinct linked `ExternalThreadId` values from its correspondence, fetches Gmail messages for those known threads, and imports only unseen `ExternalMessageId` values into the same job.
3. Extend `JobTrackerApi/Services/GmailOAuthService.cs` with the thread-level retrieval helper(s) needed by that controller path, and keep diagnostics bounded to counts, ids, timestamps, and connection state rather than full message bodies.
4. Expand `JobTrackerApi.Tests/GmailControllerTests.cs` to cover successful refresh with a new inbound reply, successful refresh with a new user-sent reply, duplicate-only refresh, disconnected Gmail state, and invalid/inaccessible job handling.
## 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.
- [ ] The refresh path operates on already-linked Gmail thread ids for one owned job; it does not introduce inbox-wide watch/history infrastructure for this slice.
- [ ] New Gmail replies import into the same `JobApplication` with existing duplicate protection based on `ExternalMessageId`.
- [ ] The refresh contract exposes enough status to tell whether the run imported new messages, found only duplicates, or could not run because Gmail/job state was invalid.
## 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.
- Confirm the updated tests assert at least one new-message refresh, one duplicate-only refresh, and one failure-path outcome.
## 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.
- Signals added/changed: linked-thread refresh result counts, last refresh/sync timestamp updates, and explicit disconnected/invalid-job outcomes.
- How a future agent inspects this: read the refresh DTO and controller action in `JobTrackerApi/Controllers/GmailController.cs` and the focused assertions in `JobTrackerApi.Tests/GmailControllerTests.cs`.
- Failure state exposed: the API should make it obvious whether nothing happened because there were no linked threads, Gmail was disconnected, every message was already imported, or the job was not accessible.
## 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.
- `JobTrackerApi/Controllers/GmailController.cs`current job-aware Gmail matching and import endpoints.
- `JobTrackerApi/Services/GmailOAuthService.cs`current Gmail list/detail helpers and connection status updates.
- `JobTrackerApi.Tests/GmailControllerTests.cs`existing Gmail controller test coverage.
- `JobTrackerApi/Program.cs` — existing Gmail/correspondence runtime wiring and compatibility guards.
## 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.
- `JobTrackerApi/Controllers/GmailController.cs` — adds the linked-thread refresh contract for one job.
- `JobTrackerApi/Services/GmailOAuthService.cs`adds thread-fetch support used by refresh.
- `JobTrackerApi.Tests/GmailControllerTests.cs` — proves refresh success, duplicate-only, and failure-path behavior.
- `JobTrackerApi/Program.cs` — updates any wiring needed for the new refresh flow or diagnostics.