chore(M001/S01): auto-commit after research-slice
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
# M001: Gmail and draft quality loop
|
||||
|
||||
**Gathered:** 2026-03-24
|
||||
**Status:** Ready for planning
|
||||
|
||||
## Project Description
|
||||
|
||||
This milestone upgrades an existing personal job-tracking app into a workflow the user can trust every day. The user still finds jobs outside the app and applies outside the app, but once a job is imported, the app should become the place where the user prepares stronger application material, imports relevant Gmail correspondence, generates follow-up and reply drafts, and keeps the process organized without losing the thread.
|
||||
|
||||
## Why This Milestone
|
||||
|
||||
The codebase already has job import, Gmail import, CV tooling, AI-assisted draft generation, readiness analysis, and per-job workspaces. The problem is not total feature absence; it is that the two most important weak points in the current product are Gmail import and AI draft quality. Those are foundational trust surfaces. If Gmail import feels dumb or the AI drafts feel weak, the app does not earn a place in the user’s daily job-search loop. This milestone focuses on making the existing workflow materially better before broadening the product outward.
|
||||
|
||||
## User-Visible Outcome
|
||||
|
||||
### When this milestone is complete, the user can:
|
||||
|
||||
- import a job found on an external job site, generate a tailored application package, and use it as the basis for a real application outside the app
|
||||
- connect Gmail, import the right correspondence into the right job with less cleanup, and generate follow-up or reply drafts from real context
|
||||
|
||||
### Entry point / environment
|
||||
|
||||
- Entry point: browser UI starting from the job table and per-job workspace
|
||||
- Environment: browser + local/dev or deployed web app backed by API, database, Gmail OAuth, and local AI service
|
||||
- Live dependencies involved: database, Gmail OAuth/import, local AI service, optional SMTP for reminder/follow-up workflows
|
||||
|
||||
## Completion Class
|
||||
|
||||
- Contract complete means: the relevant API endpoints, UI flows, persisted job/correspondence state, and draft-generation paths are wired and verified with tests and artifact checks
|
||||
- Integration complete means: real Gmail import, job-linked correspondence, and AI draft generation work together across frontend, API, and AI service boundaries
|
||||
- Operational complete means: the workflow survives real auth/config/service conditions well enough that a user can use it repeatedly without hidden setup traps or dangerous outbound automation
|
||||
|
||||
## Final Integrated Acceptance
|
||||
|
||||
To call this milestone complete, we must prove:
|
||||
|
||||
- a user can import a real job, generate a stronger tailored CV and cover-letter package, and save/edit that material in the job workspace
|
||||
- a user can connect Gmail, import the correct message or thread into a job, and then generate a context-aware follow-up or reply draft from that imported correspondence
|
||||
- the full loop from job table → follow-up/dashboard → individual job workspace works cleanly enough for real repeated use, and no part of the milestone relies on auto-send or auto-apply behavior
|
||||
|
||||
## Risks and Unknowns
|
||||
|
||||
- Gmail matching quality may still be noisy — if message-to-job association is weak, the correspondence workflow will not feel trustworthy
|
||||
- Draft quality may plateau even with better prompts — if outputs still feel generic, the main value promise remains unproven
|
||||
- Existing capability may be present but fragmented — if the workflow still feels scattered across tabs and screens, the product will not feel like one coherent workspace
|
||||
- The daily overview may still under-signal urgency — if the table and dashboard do not turn state into action, tracking value stays abstract
|
||||
|
||||
## Existing Codebase / Prior Art
|
||||
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — existing Gmail OAuth, message listing, and import endpoints
|
||||
- `JobTrackerApi/Services/GmailOAuthService.cs` — Gmail token handling and Gmail API access
|
||||
- `JobTrackerApi/Controllers/JobImportController.cs` — existing external job import preview flow
|
||||
- `JobTrackerApi/Controllers/JobApplicationsController.cs` — current candidate-fit, focus-plan, interview-prep, readiness, tailored-CV, and follow-up draft surfaces
|
||||
- `JobTrackerApi/Controllers/ProfileCvController.cs` — profile CV upload, extraction, parse, rebuild, and improve flows
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — current Gmail connection/import UI inside job correspondence
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — current per-job AI tabs, draft editing, attachment context selection, and readiness UI
|
||||
- `job-tracker-ui/src/components/JobTable.tsx` — job table surface that should remain the primary daily control view
|
||||
- `job-tracker-ui/src/components/DashboardView.tsx` — dashboard/follow-up surface that should become a clearer urgency view
|
||||
- `tools/summarizer/app.py` — local AI service boundary for summarization and extraction
|
||||
|
||||
> See `.gsd/DECISIONS.md` for all architectural and pattern decisions — it is an append-only register; read it during planning, append to it during execution.
|
||||
|
||||
## Relevant Requirements
|
||||
|
||||
- R001 — establishes the import-first workflow around jobs discovered elsewhere
|
||||
- R002 — improves Gmail import into something the user can trust as part of the daily workflow
|
||||
- R003 — raises AI application draft quality from present to genuinely useful
|
||||
- R004 — turns imported job and correspondence context into better reply/follow-up drafting
|
||||
- R005 — preserves the job table as the first control surface
|
||||
- R006 — makes follow-up/dashboard views better at surfacing urgency and next actions
|
||||
- R007 — strengthens the individual job workspace as the place to do focused work
|
||||
- R008 — keeps all outbound communication manual and user-controlled
|
||||
- R009 — keeps milestone scope optimized for an individual user, not a recruiter workflow
|
||||
- R010 — ensures tracking continuity across manual updates and imported correspondence
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- smarter Gmail message/thread import and job matching quality
|
||||
- better use of imported correspondence as context for reply and follow-up drafting
|
||||
- stronger tailored CV and cover-letter generation quality
|
||||
- tighter daily-use flow across job table, follow-up/dashboard, and individual job workspace
|
||||
- coherence improvements that make existing AI and tracking capability feel like one product loop
|
||||
|
||||
### Out of Scope / Non-Goals
|
||||
|
||||
- automatic job application submission
|
||||
- automatic sending of follow-up or reply emails
|
||||
- turning the app into a job-discovery product that replaces external job boards
|
||||
- recruiter CRM, shared pipelines, or team collaboration workflows
|
||||
- broad product expansion unrelated to Gmail import quality, draft quality, or the daily control loop
|
||||
|
||||
## Technical Constraints
|
||||
|
||||
- preserve the no-auto-send trust boundary across all AI-assisted communication flows
|
||||
- build on the existing React + ASP.NET Core + local FastAPI service architecture rather than replacing it
|
||||
- respect existing Gmail OAuth and job-linked correspondence patterns already in the codebase
|
||||
- keep draft generation grounded in real profile CV, job, attachment, and correspondence context rather than generic prompts alone
|
||||
- maintain an individual-first UX even where admin/multi-user code exists in the repo
|
||||
|
||||
## Integration Points
|
||||
|
||||
- Gmail API — used for message listing, thread retrieval, and import into job correspondence
|
||||
- local AI service — used for summarization, extraction, and draft generation context building
|
||||
- ASP.NET Core API + EF Core database — persists jobs, correspondence, CV/profile state, and draft outputs
|
||||
- browser UI — presents the table/dashboard/job-workspace control flow that must feel coherent after this milestone
|
||||
|
||||
## Open Questions
|
||||
|
||||
- How far matching confidence and message-to-job suggestion logic can be pushed with the current Gmail data model — current thinking: prove it through real import UX in S01 rather than abstract matching rules
|
||||
- Whether prompt/workflow changes alone are enough to make drafts feel strong, or whether UI/context shaping is the bigger lever — current thinking: test both because “quality” here is partly generation and partly surrounding workflow
|
||||
- Which existing dashboard/table elements should be simplified versus enriched — current thinking: prioritize action clarity over adding more analytics first
|
||||
@@ -0,0 +1,40 @@
|
||||
# M001 Discussion Log
|
||||
|
||||
## Exchange — 2026-03-24T08:14:04.663Z
|
||||
|
||||
### M003 Gate
|
||||
|
||||
For M003 — deeper external awareness and automation like smarter inbox handling beyond the first Gmail improvements — should I write a draft for later?
|
||||
|
||||
- **Write draft for later (Recommended)** — Keep the current intent as a draft now, then do a focused discussion when this milestone comes up.
|
||||
- **Discuss now** — Use this session to deepen M003 enough for a full context file.
|
||||
- **Just queue it** — Record the milestone only and leave discussion for a future session from scratch.
|
||||
|
||||
**Selected:** Write draft for later (Recommended)
|
||||
|
||||
---
|
||||
## Exchange — 2026-03-24T08:14:27.657Z
|
||||
|
||||
### M004 Gate
|
||||
|
||||
For M004 — launch hardening, validation, trust, clarity, and operational polish — should I write a draft for later?
|
||||
|
||||
- **Write draft for later (Recommended)** — Capture the current intent as a draft now and refine it when the product is closer to launch hardening.
|
||||
- **Discuss now** — Use this session to deepen M004 enough for a full context file.
|
||||
- **Just queue it** — Record the milestone only and leave discussion for a future session from scratch.
|
||||
|
||||
**Selected:** Write draft for later (Recommended)
|
||||
|
||||
---
|
||||
## Exchange — 2026-03-24T08:14:59.499Z
|
||||
|
||||
### M001 Check
|
||||
|
||||
I verified the current code has job import, Gmail import, CV tooling, and AI draft surfaces already present; should M001 be written as a coherence-and-quality milestone around those real capabilities?
|
||||
|
||||
- **Yes, write it (Recommended)** — Write M001 around smarter Gmail import, stronger drafts, and the daily control loop.
|
||||
- **Not quite — adjust it** — The milestone emphasis is off and needs correction before writing.
|
||||
|
||||
**Selected:** Yes, write it (Recommended)
|
||||
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"integrationBranch": "main"
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
# M001: Gmail and draft quality loop
|
||||
|
||||
**Vision:** Turn the existing job tracker into a daily-use personal job-search workspace where Gmail import and AI drafting are strong enough to trust, while preserving manual control over all real-world sending and applying.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- User can import a job found elsewhere, generate a tailored CV and cover-letter package that feels specific enough to start from, and save/edit that package inside the job workspace.
|
||||
- User can connect Gmail, import the right message or thread into a job with less cleanup than before, and see the imported correspondence reflected in that job’s timeline/workspace.
|
||||
- User can generate a follow-up or reply draft grounded in the imported correspondence and saved job/application context.
|
||||
- The daily loop of job table → follow-up/dashboard → individual job workspace feels coherent and actionable for an individual user.
|
||||
- No part of the milestone auto-sends email or auto-applies to jobs.
|
||||
|
||||
## Key Risks / Unknowns
|
||||
|
||||
- Gmail import may still feel unreliable if matching and import clarity do not improve enough to reduce manual cleanup.
|
||||
- AI draft quality may still feel generic even though the draft surfaces already exist.
|
||||
- The workflow may remain fragmented if table/dashboard/job-detail changes do not land as one coherent loop.
|
||||
- Real value may depend on live Gmail + AI + persisted job context wiring, not isolated endpoint improvements.
|
||||
|
||||
## Proof Strategy
|
||||
|
||||
- Gmail import reliability and trust → retire in S01 by proving a user can connect Gmail, review likely messages or threads for a job, and import the right correspondence into that job with clearer matching behavior.
|
||||
- AI draft quality and usefulness → retire in S02 by proving imported job context plus profile/CV context produce tailored drafts the user can edit and save as actual working material.
|
||||
- Reply/follow-up assistance grounded in real context → retire in S03 by proving imported correspondence and saved draft state feed a useful reply/follow-up drafting flow.
|
||||
- Workflow coherence across daily surfaces → retire in S04 and S05 by proving the table/dashboard/job workspace work as one control loop and by re-checking the whole loop end-to-end.
|
||||
|
||||
## Verification Classes
|
||||
|
||||
- Contract verification: backend/frontend tests, artifact checks for new endpoints and UI flows, persisted state checks, import/draft wiring verification
|
||||
- Integration verification: real Gmail OAuth/import plus live AI-service-backed draft generation exercised through the app
|
||||
- Operational verification: repeated use of the workflow across auth/config/service boundaries without dangerous outbound automation
|
||||
- UAT / human verification: whether Gmail import feels trustworthy and whether drafts feel strong enough to start from in real use
|
||||
|
||||
## Milestone Definition of Done
|
||||
|
||||
This milestone is complete only when all are true:
|
||||
|
||||
- all slice deliverables are complete
|
||||
- Gmail import, correspondence state, and draft-generation surfaces are actually wired together
|
||||
- the real browser entrypoint exists and is exercised through the table/dashboard/job loop
|
||||
- success criteria are re-checked against live behavior, not just artifact presence
|
||||
- final integrated acceptance scenarios pass
|
||||
|
||||
## Requirement Coverage
|
||||
|
||||
- Covers: R001, R002, R003, R004, R005, R006, R007, R008, R010
|
||||
- Partially covers: R009
|
||||
- Leaves for later: R011, R012, R013
|
||||
- Orphan risks: none
|
||||
|
||||
## Slices
|
||||
|
||||
- [ ] **S01: Smarter Gmail import and matching** `risk:high` `depends:[]`
|
||||
> After this: User can connect Gmail, review likely messages or threads for a job, and import correspondence with much better matching confidence and less manual cleanup.
|
||||
|
||||
- [ ] **S02: Stronger AI application package drafting** `risk:high` `depends:[S01]`
|
||||
> After this: From an imported job plus profile/CV context, the app generates materially better tailored CV and cover-letter drafts that feel specific and usable.
|
||||
|
||||
- [ ] **S03: Reply and follow-up drafting from real thread context** `risk:medium` `depends:[S01,S02]`
|
||||
> After this: Inside a job, the user can generate follow-up and reply drafts grounded in imported correspondence and saved application context, then edit them before sending manually.
|
||||
|
||||
- [ ] **S04: Daily control loop surfaces** `risk:medium` `depends:[S01,S03]`
|
||||
> After this: The job table works as the primary overview and the follow-up/dashboard surfaces clearly show what needs attention next for an individual user.
|
||||
|
||||
- [ ] **S05: End-to-end trust and workflow polish** `risk:low` `depends:[S01,S02,S03,S04]`
|
||||
> After this: The full loop works cleanly in a real environment: import job → generate package → apply externally → import/update correspondence → draft follow-up/reply → track progress confidently.
|
||||
|
||||
## Boundary Map
|
||||
|
||||
### S01 → S02
|
||||
|
||||
Produces:
|
||||
- improved Gmail import workflow in `job-tracker-ui/src/components/Correspondence.tsx` that yields job-linked imported correspondence with clearer message/thread selection behavior
|
||||
- stronger backend correspondence import surface in `JobTrackerApi/Controllers/GmailController.cs` and related persistence so imported messages reliably attach to `JobApplication` records
|
||||
- stable job/correspondence linkage that later draft-generation flows can consume as trusted context
|
||||
|
||||
Consumes:
|
||||
- nothing (first slice)
|
||||
|
||||
### S01 → S03
|
||||
|
||||
Produces:
|
||||
- imported correspondence records tied to a specific job and available through the existing per-job correspondence/timeline surfaces
|
||||
- message/thread metadata good enough for later reply/follow-up draft context assembly
|
||||
- a verified Gmail connection/import path that downstream slices can rely on
|
||||
|
||||
Consumes:
|
||||
- nothing (first slice)
|
||||
|
||||
### S02 → S03
|
||||
|
||||
Produces:
|
||||
- improved application package generation via `JobTrackerApi/Controllers/JobApplicationsController.cs` returning stronger tailored CV and cover-letter outputs tied to a job
|
||||
- persisted draft state in the job workspace so later follow-up/reply flows can reuse saved application context
|
||||
- clearer frontend editing/saving behavior in `job-tracker-ui/src/components/JobDetailsDialog.tsx`
|
||||
|
||||
Consumes from S01:
|
||||
- imported correspondence and job-linked message context
|
||||
|
||||
### S03 → S04
|
||||
|
||||
Produces:
|
||||
- reply/follow-up draft flow grounded in job + correspondence + saved application package context
|
||||
- explicit manual-send boundary in the job workspace UI and backend behavior
|
||||
- job-level indicators that a follow-up/reply is ready, missing context, or needs action
|
||||
|
||||
Consumes from S01:
|
||||
- Gmail-imported correspondence context
|
||||
|
||||
Consumes from S02:
|
||||
- saved tailored CV / cover-letter / application package context
|
||||
|
||||
### S04 → S05
|
||||
|
||||
Produces:
|
||||
- table/dashboard surfaces that summarize readiness, follow-up urgency, and next actions for individual users
|
||||
- clearer navigation hierarchy across table, follow-up/dashboard, and individual job workspace
|
||||
- stable daily-use control loop to validate in final integration
|
||||
|
||||
Consumes from S01:
|
||||
- correspondence state and Gmail import outcomes
|
||||
|
||||
Consumes from S03:
|
||||
- follow-up/reply drafting signals and job-level action state
|
||||
@@ -0,0 +1,110 @@
|
||||
# S01 — Research
|
||||
|
||||
**Date:** 2026-03-24
|
||||
|
||||
## Summary
|
||||
|
||||
S01 owns **R001** and **R002** directly, and it materially supports **R010** because imported correspondence becomes part of the job timeline and later follow-up context. The codebase already has a complete Gmail OAuth path, a Gmail message listing endpoint, single-message and thread import endpoints, and a per-job correspondence UI. The gap is not missing Gmail plumbing; it is that matching is still mostly manual. The backend returns raw Gmail search results, while the frontend (`job-tracker-ui/src/components/Correspondence.tsx`) applies a lightweight client-side score based only on the freeform query, snippet text, and already-imported subjects. That does not use the actual job/company context strongly enough to satisfy the “less manual cleanup” bar in R002.
|
||||
|
||||
The best approach is to keep the existing OAuth/import flow and add a **job-aware matching layer** rather than replacing the Gmail integration. In practice that means: enrich backend candidate discovery around a specific `JobApplication`, return grouped thread/message suggestions with explicit match reasons/confidence inputs, and then update the correspondence dialog to present those suggestions first. This follows the current architecture cleanly and preserves the no-auto-send boundary from D002. The React side should keep async work consolidated instead of scattering additional fetches across effects; the loaded `react-best-practices` skill is relevant here, especially `async-parallel` and `client-event-listeners`.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Add a dedicated **job-scoped Gmail matching surface** on top of the existing endpoints instead of trying to make the current generic `/api/gmail/messages` search UI smarter only in the browser.
|
||||
|
||||
Recommended shape:
|
||||
- Backend: add a job-aware endpoint in `JobTrackerApi/Controllers/GmailController.cs` that accepts `jobApplicationId` and optional overrides, loads the job + company context, builds Gmail queries from `JobTitle`, `Company.Name`, `Company.RecruiterEmail`, recruiter name, and recent imported correspondence, then returns ranked message/thread candidates with **match reasons** and enough metadata for import decisions.
|
||||
- Persistence: if the planner wants durable thread-aware behavior, extend `Models/Correspondence.cs` beyond `ExternalMessageId` to also persist at least `ExternalThreadId` and raw sender/recipient metadata. This is the cleanest way to support downstream S03 reply/follow-up context without re-deriving it later.
|
||||
- Frontend: refactor `job-tracker-ui/src/components/Correspondence.tsx` so the Gmail tab consumes enriched API data instead of doing primary ranking locally. `JobDetailsDialog.tsx` already loads the full job; passing the job or a reduced job-context prop into `Correspondence` is cheaper than forcing the Gmail tab to rediscover job facts.
|
||||
|
||||
Why this approach:
|
||||
- It uses the existing Gmail OAuth/token flow unchanged.
|
||||
- It moves matching logic to the backend where job context, dedupe checks, and future heuristics are easier to test.
|
||||
- It avoids over-investing in fragile client-only heuristics.
|
||||
- It creates a natural seam for S03, where better thread metadata and message provenance will matter again.
|
||||
|
||||
## Implementation Landscape
|
||||
|
||||
### Key Files
|
||||
|
||||
- `JobTrackerApi/Controllers/GmailController.cs` — current Gmail API surface. Has `/status`, `/connect-url`, `/messages`, `/import`, and `/import-thread`. Import endpoints already attach messages to `JobApplication` and dedupe by `Correspondence.ExternalMessageId`, but discovery is still generic and not job-aware.
|
||||
- `JobTrackerApi/Services/GmailOAuthService.cs` — Gmail OAuth/token refresh and Gmail API access. `ListMessagesAsync` currently calls the Gmail list endpoint and then does an **N+1** sequence of `GetMessageAsync` calls to hydrate summaries. There is no thread-specific fetch API, no job-aware query builder, and no ranking/match-reason contract here yet.
|
||||
- `job-tracker-ui/src/components/Correspondence.tsx` — the main S01 frontend surface. It opens the Gmail dialog, loads `/gmail/status`, loads `/gmail/messages`, groups by `threadId`, and sorts using `scoreMessage(...)`. Current suggestions come from existing correspondence subjects, not from job/company/recruiter context.
|
||||
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — already loads the full `JobApplication` record and hosts the Correspondence tab. This is the easiest place to pass job context into `Correspondence` instead of refetching it inside the Gmail tab.
|
||||
- `job-tracker-ui/src/types.ts` — frontend contracts for `GmailStatus`, `GmailMessageSummary`, and `CorrespondenceMessage`. Any enriched matching response or persisted metadata expansion needs updates here.
|
||||
- `Models/Correspondence.cs` — currently stores `From`, `Subject`, `Channel`, `ExternalMessageId`, `Content`, and `Date`. No `ThreadId`, no original Gmail sender/recipient fields, and no match/debug metadata.
|
||||
- `Data/JobTrackerContext.cs` — EF relationships and ownership filters. `JobApplication`, `Company`, and `GmailConnection` are user-scoped via query filters; new Gmail-matching endpoints should continue loading jobs through this context rather than bypassing ownership.
|
||||
- `Models/Company.cs` and `Models/JobApplication.cs` — hold the matching signals that the current Gmail UI ignores: `Company.Name`, `RecruiterEmail`, `RecruiterName`, `JobTitle`, `JobUrl`, `ShortSummary`, and existing correspondence/timeline relationships.
|
||||
- `JobTrackerApi/Controllers/CorrespondenceController.cs` — current create/list/delete API for job-linked messages. If S01 persists extra Gmail metadata, this contract may need to expose it to the UI and timeline.
|
||||
- `JobTrackerApi/Controllers/JobApplicationsController.cs` — downstream dependency surface. It already reads `Correspondences` for follow-up drafting and timeline assembly, so better message/thread metadata here directly helps S03.
|
||||
- `JobTrackerApi/Program.cs` — important migration/backfill guardrail. The app manually ensures legacy SQLite/MySQL columns such as `Correspondences.Subject`, `Channel`, and `ExternalMessageId`. If S01 adds new persistence columns, these compatibility blocks must be updated alongside the EF migration.
|
||||
- `JobTrackerApi.Tests/GmailControllerTests.cs` — only covers the empty-thread import validation case today. Good starting point, but far below the verification level needed for S01.
|
||||
- `job-tracker-ui/src/job-details-generated-drafts.test.tsx` — representative React test style: mock `api`, render `JobDetailsDialog`, assert visible tab behavior. Follow this pattern for new Gmail suggestion/import UI tests.
|
||||
|
||||
### Build Order
|
||||
|
||||
1. **Decide and lock the backend contract first.**
|
||||
- Prove what a “smarter match” response looks like: message/thread grouping, rank/confidence, reasons, imported/already-linked flags, and import actions.
|
||||
- This is the riskiest part and unblocks everything else.
|
||||
|
||||
2. **Implement job-aware matching in `GmailController` + supporting service/helpers.**
|
||||
- Load `JobApplication` with `Company`.
|
||||
- Build candidate Gmail queries from job/company/recruiter data.
|
||||
- Merge/dedupe results by message id or thread id.
|
||||
- Compute match reasons server-side.
|
||||
- Keep existing `/import` and `/import-thread` behavior unless the new contract proves they need richer return payloads.
|
||||
|
||||
3. **Only after the contract is stable, refactor `Correspondence.tsx`.**
|
||||
- Replace `scoreMessage(...)` as the primary ranking engine with server-provided ranking/reasons.
|
||||
- Pass job context from `JobDetailsDialog.tsx` rather than introducing another job fetch in the correspondence tab.
|
||||
- Keep manual query override/search available as a fallback, not the primary UX.
|
||||
|
||||
4. **Then extend persistence if needed for thread continuity.**
|
||||
- Add correspondence metadata only if the chosen backend contract needs it for dedupe, import clarity, or future reply context.
|
||||
- If added, update model, migration, and `Program.cs` compatibility shims together.
|
||||
|
||||
5. **Finish with tests.**
|
||||
- Backend tests for matching/import behavior first.
|
||||
- Frontend tests for the new Gmail suggestion UI second.
|
||||
|
||||
### Verification Approach
|
||||
|
||||
- Backend unit/integration tests:
|
||||
- `dotnet test JobTrackerApi.Tests`
|
||||
- Add tests for: job-aware candidate endpoint contract, dedupe behavior for already-imported messages, ownership-scoped job lookup, and thread import summary results.
|
||||
- Frontend tests:
|
||||
- `npm test -- --watch=false` from `job-tracker-ui`
|
||||
- Add React tests covering: Gmail tab rendering ranked suggestions, showing match reasons, import button states, and fallback/manual search behavior.
|
||||
- Contract/manual verification:
|
||||
- Open a job in `JobDetailsDialog` → Correspondence tab.
|
||||
- Confirm Gmail connection state still works.
|
||||
- Confirm the Gmail tab now shows job-relevant suggestions before freeform searching.
|
||||
- Import a single message and a full thread; verify the job timeline/correspondence list updates and duplicates are skipped.
|
||||
- If persistence changes land:
|
||||
- Verify schema startup still succeeds on existing dev DBs because `JobTrackerApi/Program.cs` legacy `EnsureColumn(...)` blocks are easy to miss.
|
||||
|
||||
## Constraints
|
||||
|
||||
- `Data/JobTrackerContext.cs` applies ownership query filters to `Company`, `JobApplication`, and `GmailConnection`. Any new Gmail matching endpoint must keep loading through EF-scoped entities, not raw unfiltered ids.
|
||||
- `JobTrackerApi/Services/GmailOAuthService.cs` currently exposes only message list/detail methods. There is no reusable thread-fetch or search-aggregation abstraction yet.
|
||||
- `JobTrackerApi/Program.cs` contains manual schema repair code for SQLite/MySQL. Adding correspondence metadata requires updating both EF migration artifacts and these runtime compatibility paths.
|
||||
- `Models/Correspondence.cs` does not currently preserve Gmail thread identity or raw sender/recipient fields, which limits downstream thread-aware UX.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- **Leaving ranking in the browser** — `Correspondence.tsx` can polish server results, but if the primary intelligence stays in `scoreMessage(...)`, S01 will remain query-driven and fragile.
|
||||
- **Adding columns without updating `Program.cs`** — this repo relies on startup-time `EnsureColumn(...)` logic for legacy/dev databases; migration-only changes are incomplete here.
|
||||
- **Duplicating job fetches in the dialog tree** — `JobDetailsDialog.tsx` already owns the job record. Per the `react-best-practices` guidance (`async-parallel`, `client-event-listeners`), keep async fetching consolidated and avoid adding more dialog-level waterfalls or duplicated global listeners.
|
||||
- **Treating thread import as enough without thread metadata** — importing all messages in a thread helps today, but without persisting thread identity the app still cannot reason clearly about thread continuity later.
|
||||
|
||||
## Open Risks
|
||||
|
||||
- Gmail search quality may still be noisy even after better query construction; the planner should expect one iteration on ranking heuristics once real data is exercised.
|
||||
- `ListMessagesAsync` is sequential and could become noticeably slow if the new matching flow issues multiple Gmail searches per job. If that happens, batching/parallelization inside the Gmail service becomes part of S01, not a later optimization.
|
||||
|
||||
## Skills Discovered
|
||||
|
||||
| Technology | Skill | Status |
|
||||
|------------|-------|--------|
|
||||
| React | `react-best-practices` | available |
|
||||
| ASP.NET Core | `openai/skills@aspnet-core` | installed |
|
||||
Reference in New Issue
Block a user