chore(M001/S01): auto-commit after plan-slice
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -1,56 +1,55 @@
|
||||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 5
|
||||
estimated_files: 4
|
||||
skills_used:
|
||||
- best-practices
|
||||
- react-best-practices
|
||||
- test
|
||||
---
|
||||
|
||||
# T02: Persist Gmail thread metadata and harden import continuity
|
||||
# T02: Surface live Gmail thread continuity in the job workspace
|
||||
|
||||
**Slice:** S01 — Smarter Gmail import and matching
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Make imported Gmail correspondence durable enough to support real thread continuity. This task extends persistence and import handling so that once the user chooses a suggested Gmail message or thread, the app keeps the metadata needed for dedupe, timeline continuity, and later reply/follow-up context instead of collapsing everything down to a bare message body.
|
||||
Complete S01 in the UI by turning the existing ranked Gmail import tab into a live linked-thread workspace. The executor should preserve the current ranked suggestion/import flow, then layer in automatic refresh for already-linked Gmail threads so the user sees new replies appear on the same job without using the import action again.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Extend `Models/Correspondence.cs` so Gmail imports can retain thread/message identity and sender/recipient metadata that downstream slices can trust.
|
||||
2. Update `JobTrackerApi/Controllers/GmailController.cs` import paths and `JobTrackerApi/Controllers/CorrespondenceController.cs` response behavior so imported records populate and expose the new Gmail metadata while keeping the existing no-auto-send boundary intact.
|
||||
3. Update `JobTrackerApi/Program.cs` startup compatibility guards for SQLite/MySQL so older dev databases can gain the new correspondence columns without breaking local startup.
|
||||
4. Add or extend `JobTrackerApi.Tests/GmailControllerTests.cs` assertions for repeat single-message imports, repeat thread imports, and import result payloads that distinguish imported vs skipped work.
|
||||
1. Inspect the current Gmail UI in `job-tracker-ui/src/components/Correspondence.tsx`, the host wiring in `job-tracker-ui/src/components/JobDetailsDialog.tsx`, and the existing component test in `job-tracker-ui/src/correspondence-gmail-import.test.tsx`.
|
||||
2. Update `job-tracker-ui/src/types.ts` and `job-tracker-ui/src/components/Correspondence.tsx` to consume the new backend linked-thread refresh contract and track refresh/loading/freshness state separately from the ranked import-suggestion state.
|
||||
3. Wire `job-tracker-ui/src/components/Correspondence.tsx` so already-linked threads refresh automatically at the right moment in the job workspace flow, refresh the rendered correspondence list after sync, and make the linked/live state legible in the UI.
|
||||
4. Extend `job-tracker-ui/src/correspondence-gmail-import.test.tsx` to prove the continuity path: after a thread is already linked, a refresh brings in a later Gmail reply and renders it on the same job without another import action.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] Imported Gmail correspondence keeps message/thread identity plus sender/recipient metadata in `Models/Correspondence.cs` rather than forcing later slices to re-derive it.
|
||||
- [ ] Import endpoints clearly report imported vs skipped outcomes and continue deduping on repeat imports.
|
||||
- [ ] Runtime schema guards in `JobTrackerApi/Program.cs` are updated alongside the model change so legacy/dev databases remain bootable.
|
||||
- [ ] The UI keeps ranked job-aware Gmail suggestions for first import while clearly distinguishing already-linked live threads from new import candidates.
|
||||
- [ ] Linked-thread refresh happens through the new backend contract and updates the visible correspondence list without requiring the user to click an import button again.
|
||||
- [ ] The React test proves the continuity path, not just the original ranked-import path.
|
||||
|
||||
## Verification
|
||||
|
||||
- `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests`
|
||||
- Confirm the tests prove duplicate single-message import handling, duplicate thread import handling, and the enriched import payload contract.
|
||||
- `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Manually inspect the Correspondence dialog to confirm linked-thread state, refresh/loading state, and the newly synced message all appear in the workspace.
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: persisted Gmail metadata on correspondence records and explicit imported/skipped counts from Gmail import actions.
|
||||
- How a future agent inspects this: inspect `Models/Correspondence.cs`, the import payloads in `JobTrackerApi/Controllers/GmailController.cs`, and startup column guards in `JobTrackerApi/Program.cs`.
|
||||
- Failure state exposed: repeat imports should now reveal whether the issue is dedupe, missing metadata persistence, or schema mismatch on startup.
|
||||
- Signals added/changed: visible linked/live thread state, refresh progress/freshness state, and clearer no-new-messages vs failure feedback.
|
||||
- How a future agent inspects this: run `job-tracker-ui/src/correspondence-gmail-import.test.tsx` and inspect the Gmail area in `job-tracker-ui/src/components/Correspondence.tsx`.
|
||||
- Failure state exposed: the UI should distinguish refresh failure, disconnected Gmail, no linked threads, and successful refresh with zero new messages.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — T01 job-aware matching/import contract and existing import behavior.
|
||||
- `Models/Correspondence.cs` — current correspondence persistence model.
|
||||
- `JobTrackerApi/Controllers/CorrespondenceController.cs` — current correspondence list/create/delete surface.
|
||||
- `JobTrackerApi/Program.cs` — runtime schema repair path that must stay aligned with new columns.
|
||||
- `JobTrackerApi.Tests/GmailControllerTests.cs` — backend Gmail coverage expanded in T01.
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — current ranked Gmail import UI.
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — host dialog that owns the job workspace.
|
||||
- `job-tracker-ui/src/types.ts` — frontend Gmail and correspondence contracts.
|
||||
- `job-tracker-ui/src/correspondence-gmail-import.test.tsx` — existing Gmail import component test.
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — T01 backend refresh contract consumed by the UI.
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `Models/Correspondence.cs` — persists Gmail message/thread and sender/recipient metadata.
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — populates and reports the new import metadata cleanly.
|
||||
- `JobTrackerApi/Controllers/CorrespondenceController.cs` — exposes the enriched correspondence records back to the UI.
|
||||
- `JobTrackerApi/Program.cs` — keeps legacy/dev DB startup safe after the schema change.
|
||||
- `JobTrackerApi.Tests/GmailControllerTests.cs` — proves continuity and duplicate-import behavior.
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — renders linked-thread refresh state and continuity behavior.
|
||||
- `job-tracker-ui/src/types.ts` — matches the backend refresh contract.
|
||||
- `job-tracker-ui/src/correspondence-gmail-import.test.tsx` — proves the no-manual-reimport continuity path.
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — includes any required wiring for the refreshed workspace flow.
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
estimated_steps: 4
|
||||
estimated_files: 4
|
||||
skills_used:
|
||||
- react-best-practices
|
||||
- test
|
||||
---
|
||||
|
||||
# T03: Wire ranked Gmail suggestions into the job workspace UI
|
||||
|
||||
**Slice:** S01 — Smarter Gmail import and matching
|
||||
**Milestone:** M001
|
||||
|
||||
## Description
|
||||
|
||||
Deliver the user-facing part of the slice in the actual job workspace. The Correspondence tab should stop acting like a generic Gmail search box and instead open with job-aware ranked suggestions from the backend, explain why each candidate is relevant, let the user override with manual search when needed, and refresh the job-linked correspondence view after import.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Update `job-tracker-ui/src/types.ts` to reflect the new backend candidate contract and enriched correspondence metadata from T01 and T02.
|
||||
2. Pass job context from `job-tracker-ui/src/components/JobDetailsDialog.tsx` into `job-tracker-ui/src/components/Correspondence.tsx` so the Gmail tab can request job-aware suggestions without duplicating the job fetch.
|
||||
3. Refactor `job-tracker-ui/src/components/Correspondence.tsx` to consume the backend-ranked suggestions, show thread/message match reasons and import state, keep manual Gmail query override/search available, and refresh the rendered correspondence list after successful imports.
|
||||
4. Add `job-tracker-ui/src/correspondence-gmail-import.test.tsx` covering ranked suggestion rendering, reason/confidence display, thread vs single-message import actions, and refresh after import.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- [ ] The Gmail tab opens on job-aware ranked suggestions instead of using `scoreMessage(...)` as the primary intelligence.
|
||||
- [ ] The UI still supports manual Gmail searching as a fallback override, but it no longer depends on freeform query heuristics for the core experience.
|
||||
- [ ] The React test proves the user can see ranked suggestions and that importing updates the same job’s correspondence surface.
|
||||
|
||||
## Verification
|
||||
|
||||
- `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Manually inspect the dialog to confirm ranked reasons/import state are visible and the correspondence list refreshes after import.
|
||||
|
||||
## Observability Impact
|
||||
|
||||
- Signals added/changed: visible match reasons/confidence/import state in the Gmail tab and clearer import success/duplicate feedback toasts.
|
||||
- How a future agent inspects this: read `job-tracker-ui/src/correspondence-gmail-import.test.tsx` and open the Correspondence dialog in the running app.
|
||||
- Failure state exposed: the UI should distinguish no matches, already-imported candidates, loading states, and import failures instead of collapsing them into a generic empty list.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — host dialog that already owns the job record.
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — current Gmail import UI with client-side ranking.
|
||||
- `job-tracker-ui/src/types.ts` — frontend API contracts.
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — T01/T02 backend Gmail candidate and import contract.
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — passes job context into the correspondence tab.
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — renders job-aware Gmail suggestions and refreshed import behavior.
|
||||
- `job-tracker-ui/src/types.ts` — matches the updated backend contract.
|
||||
- `job-tracker-ui/src/correspondence-gmail-import.test.tsx` — proves the UI flow end to end at component level.
|
||||
Reference in New Issue
Block a user