chore: auto-commit after execute-task
GSD-Unit: M001/S06/T01
This commit is contained in:
@@ -1,64 +1,12 @@
|
||||
# S01: Smarter Gmail import and matching
|
||||
|
||||
**Goal:** Finish S01 by turning the existing job-aware Gmail import flow into a live linked-thread continuity loop for one job workspace.
|
||||
**Demo:** From a job opened in the workspace, the user connects Gmail, sees ranked thread/message suggestions for that job, imports a full thread, and later sees new inbound or user-sent Gmail replies land on the same job automatically through the linked-thread refresh flow without re-importing the thread manually.
|
||||
|
||||
S01 still owns active requirement **R002** and materially supports **R010**. The earlier groundwork already exists in code: `GET /api/gmail/job-candidates`, enriched correspondence metadata, and the ranked `Correspondence` Gmail UI are present. The remaining slice risk is now narrower but higher value: thread continuity. I am therefore grouping the remaining work into two tasks only. The first task closes the backend/runtime contract for linked-thread refresh and failure diagnosis. The second task wires that refresh into the actual job workspace so the user experiences continuity instead of a one-time import snapshot. This keeps each executor task within one fresh context window while still making every completed task produce visible user progress.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- Linked Gmail thread refresh works from already-imported thread ids stored on job correspondence and imports only newly discovered messages into that same job.
|
||||
- The refresh flow preserves duplicate safety for both inbound recruiter messages and user-sent Gmail replies.
|
||||
- The job workspace surfaces linked-thread freshness clearly enough that the user can tell the thread is live, not a stale snapshot.
|
||||
- The slice verification proves both the backend contract and the UI continuity loop in named test files plus one real Gmail UAT pass.
|
||||
|
||||
## Proof Level
|
||||
|
||||
- This slice proves: integration
|
||||
- Real runtime required: yes
|
||||
- Human/UAT required: yes
|
||||
|
||||
## Verification
|
||||
|
||||
- `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests`
|
||||
- `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Manual UAT: connect a real Gmail account, open one job workspace, import a full Gmail thread, send or receive a later reply in Gmail on that same thread, reopen or refresh the workspace, and confirm the new message appears on that job without using the import action again.
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: linked-thread refresh result counts per job (`threadsChecked`, `imported`, `skipped`), per-thread duplicate-safe status, and `lastSyncedAt`/refresh timestamps exposed through the Gmail status or refresh contract.
|
||||
- Inspection surfaces: `JobTrackerApi/Controllers/GmailController.cs`, `JobTrackerApi/Services/GmailOAuthService.cs`, `JobTrackerApi.Tests/GmailControllerTests.cs`, and the linked-thread state rendered in `job-tracker-ui/src/components/Correspondence.tsx`.
|
||||
- Failure visibility: invalid job/thread lookup, disconnected Gmail state, empty linked-thread sets, Gmail fetch failures, and duplicate-only refresh runs should each produce distinct API/UI outcomes rather than a generic silent no-op.
|
||||
- Redaction constraints: diagnostics must stay at thread/message ids, counts, timestamps, and sender labels; never log OAuth secrets or full Gmail bodies.
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `JobTrackerApi/Controllers/GmailController.cs`, `JobTrackerApi/Services/GmailOAuthService.cs`, `Models/Correspondence.cs`, `JobTrackerApi/Program.cs`, `job-tracker-ui/src/components/Correspondence.tsx`, `job-tracker-ui/src/components/JobDetailsDialog.tsx`, `job-tracker-ui/src/types.ts`.
|
||||
- New wiring introduced in this slice: a job-scoped linked-thread refresh contract plus automatic workspace refresh behavior for already-linked Gmail threads.
|
||||
- What remains before the milestone is truly usable end-to-end: Gmail import continuity should be complete after this slice; later slices still consume that trusted correspondence context for drafting and daily workflow surfaces.
|
||||
**Demo:** After this: User can connect Gmail, review likely messages or threads for a job, import a message or full thread, and trust linked Gmail threads to stay current on that job without manual re-import.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] **T01: Add linked Gmail thread refresh to the backend contract** `est:4h`
|
||||
- Why: R002 is still unmet until the app can turn a one-time import into continuing thread history for the same job.
|
||||
- Files: `JobTrackerApi/Controllers/GmailController.cs`, `JobTrackerApi/Services/GmailOAuthService.cs`, `JobTrackerApi.Tests/GmailControllerTests.cs`, `JobTrackerApi/Program.cs`
|
||||
- Do: Add a job-scoped refresh path that reads already-linked `ExternalThreadId` values for one owned job, fetches messages for those known Gmail threads, imports only unseen message ids into the same job, updates refresh timestamps/status, and exposes a clear duplicate-safe result contract. Follow D008: use bounded refresh over known imported thread ids rather than inbox-wide Gmail watch/history infrastructure.
|
||||
- [x] **T01: Add linked Gmail thread refresh to the backend contract** —
|
||||
- Files: JobTrackerApi/Controllers/GmailController.cs, JobTrackerApi/Services/GmailOAuthService.cs, JobTrackerApi.Tests/GmailControllerTests.cs, JobTrackerApi/Program.cs
|
||||
- Verify: `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests`
|
||||
- Done when: the API can refresh linked Gmail threads for one job, import new inbound or sent replies without duplicate re-imports, and tests prove success, duplicate-only, disconnected, and invalid-job cases.
|
||||
- [x] **T02: Surface live Gmail thread continuity in the job workspace** `est:3h`
|
||||
- Why: The slice is only complete when the user can see the linked thread stay current inside the real `Correspondence` workspace flow.
|
||||
- Files: `job-tracker-ui/src/components/Correspondence.tsx`, `job-tracker-ui/src/types.ts`, `job-tracker-ui/src/correspondence-gmail-import.test.tsx`, `job-tracker-ui/src/components/JobDetailsDialog.tsx`
|
||||
- Do: Wire the workspace to call the new linked-thread refresh contract automatically when appropriate for already-linked threads, show refresh/loading/freshness state in the Gmail area and correspondence list, and prove in the React test that a newly synced Gmail reply appears on the job without using the import action again.
|
||||
- [x] **T02: Surface live Gmail thread continuity in the job workspace** —
|
||||
- Files: job-tracker-ui/src/components/Correspondence.tsx, job-tracker-ui/src/types.ts, job-tracker-ui/src/correspondence-gmail-import.test.tsx, job-tracker-ui/src/components/JobDetailsDialog.tsx
|
||||
- Verify: `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Done when: the job workspace clearly distinguishes ranked import suggestions from already-linked live threads, performs linked-thread refresh through the new backend contract, and the UI test covers the no-manual-reimport continuity path.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
- `JobTrackerApi/Controllers/GmailController.cs`
|
||||
- `JobTrackerApi/Services/GmailOAuthService.cs`
|
||||
- `JobTrackerApi.Tests/GmailControllerTests.cs`
|
||||
- `JobTrackerApi/Program.cs`
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx`
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx`
|
||||
- `job-tracker-ui/src/types.ts`
|
||||
- `job-tracker-ui/src/correspondence-gmail-import.test.tsx`
|
||||
|
||||
Reference in New Issue
Block a user