chore(M001/S01): auto-commit after rewrite-docs
This commit is contained in:
@@ -5,21 +5,23 @@
|
||||
## 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 connect Gmail, import the right message or full thread into a job with less cleanup than before, and see the imported correspondence reflected in that job’s timeline/workspace.
|
||||
- After a thread is linked to a job, later inbound messages and user-sent Gmail replies appear on that job automatically without requiring the user to re-import the thread manually.
|
||||
- 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.
|
||||
- Gmail import may still feel unreliable if matching, whole-thread import, and linked-thread refresh 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.
|
||||
- Automatic Gmail thread refresh may be harder than one-time import if Gmail history/state handling is brittle or expensive.
|
||||
|
||||
## 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.
|
||||
- Gmail import reliability and trust → retire in S01 by proving a user can connect Gmail, review likely messages or threads for a job, import the right correspondence into that job, and keep a linked thread current as new replies arrive.
|
||||
- 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.
|
||||
@@ -29,14 +31,14 @@
|
||||
- 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
|
||||
- UAT / human verification: whether Gmail import feels trustworthy, whether linked threads stay current automatically enough for real use, and whether drafts feel strong enough to start from
|
||||
|
||||
## 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
|
||||
- Gmail import, linked-thread continuity, 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
|
||||
@@ -51,19 +53,19 @@ This milestone is complete only when all are true:
|
||||
## 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.
|
||||
> 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.
|
||||
|
||||
- [ ] **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.
|
||||
> After this: Inside a job, the user can generate follow-up and reply drafts grounded in imported and automatically refreshed correspondence plus 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.
|
||||
> After this: The full loop works cleanly in a real environment: import job → generate package → apply externally → import/update correspondence automatically from linked Gmail threads → draft follow-up/reply → track progress confidently.
|
||||
|
||||
## Boundary Map
|
||||
|
||||
@@ -72,7 +74,7 @@ This milestone is complete only when all are true:
|
||||
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
|
||||
- linked-thread metadata and refresh behavior stable enough that later draft-generation flows can consume correspondence as trusted context rather than a stale snapshot
|
||||
|
||||
Consumes:
|
||||
- nothing (first slice)
|
||||
@@ -82,7 +84,7 @@ Consumes:
|
||||
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
|
||||
- a verified Gmail connection/import path that downstream slices can rely on, including ongoing thread refresh after first import
|
||||
|
||||
Consumes:
|
||||
- nothing (first slice)
|
||||
@@ -95,7 +97,7 @@ Produces:
|
||||
- clearer frontend editing/saving behavior in `job-tracker-ui/src/components/JobDetailsDialog.tsx`
|
||||
|
||||
Consumes from S01:
|
||||
- imported correspondence and job-linked message context
|
||||
- imported and auto-refreshed correspondence plus job-linked message context
|
||||
|
||||
### S03 → S04
|
||||
|
||||
@@ -105,7 +107,7 @@ Produces:
|
||||
- job-level indicators that a follow-up/reply is ready, missing context, or needs action
|
||||
|
||||
Consumes from S01:
|
||||
- Gmail-imported correspondence context
|
||||
- Gmail-imported and automatically refreshed correspondence context
|
||||
|
||||
Consumes from S02:
|
||||
- saved tailored CV / cover-letter / application package context
|
||||
@@ -118,7 +120,7 @@ Produces:
|
||||
- stable daily-use control loop to validate in final integration
|
||||
|
||||
Consumes from S01:
|
||||
- correspondence state and Gmail import outcomes
|
||||
- correspondence state, Gmail import outcomes, and linked-thread refresh outcomes
|
||||
|
||||
Consumes from S03:
|
||||
- follow-up/reply drafting signals and job-level action state
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
# S01: Smarter Gmail import and matching
|
||||
|
||||
**Goal:** Make Gmail import job-aware enough that a user reviewing one imported job sees the right candidate messages/threads first, can import them with clearer confidence signals, and ends up with job-linked correspondence that needs materially less cleanup.
|
||||
**Demo:** From a job opened in the workspace, the user connects Gmail, sees ranked thread/message suggestions built from that job’s company/recruiter context, imports either one message or a full thread, and immediately sees the imported correspondence reflected on that job without any auto-send behavior.
|
||||
**Goal:** Make Gmail import job-aware enough that a user reviewing one imported job sees the right candidate messages/threads first, can import a complete thread when that is the safer choice, and then trust the linked correspondence to stay current automatically when new Gmail replies arrive or when the user sends a reply from Gmail.
|
||||
**Demo:** From a job opened in the workspace, the user connects Gmail, sees ranked thread/message suggestions built from that job’s company/recruiter context, imports either one message or a full thread, and then sees later inbound or user-sent replies from that linked Gmail thread appear on the same job without needing to manually re-pull or re-import the thread.
|
||||
|
||||
S01 directly advances active requirements **R001** and **R002**, and it also lays the continuity foundation S04 will later rely on for **R010**. The work is split backend-first because the highest risk is the matching contract itself: if ranking, dedupe, and metadata stay client-only, the UI can look nicer while the import loop still feels untrustworthy. Once that contract exists, the frontend task can focus on presenting the ranked results cleanly instead of inventing its own heuristics.
|
||||
S01 directly advances active requirements **R001**, **R002**, and **R010**. The work remains backend-first because the highest risk is now continuity, not just initial matching: if ranking, thread identity, and linked-thread refresh stay shallow, the UI can look nicer while the real correspondence loop still feels untrustworthy. The completed tasks below established the initial matching/import contract; the remaining work extends that contract into full-thread continuity so downstream drafting and tracking slices can rely on a living thread instead of a one-time import snapshot.
|
||||
|
||||
## Must-Haves
|
||||
|
||||
- A job-scoped Gmail matching API ranks candidate messages/threads for a specific `JobApplication` using company, recruiter, title, and existing correspondence signals rather than a generic inbox search alone.
|
||||
- Gmail import persists enough metadata to preserve message/thread identity, expose already-imported state, and reduce duplicate cleanup when the user imports single messages or whole threads into a job.
|
||||
- The job workspace `Correspondence` tab shows ranked Gmail suggestions with match reasons/confidence, keeps a manual search override, and refreshes the job-linked correspondence list after import.
|
||||
- The system can import an entire Gmail thread as a job-linked correspondence history, not just isolated messages, while keeping message ordering and duplicate protection intact.
|
||||
- Already-linked Gmail threads can refresh automatically so new inbound messages and user-sent replies from Gmail show up on the job without requiring a manual re-import flow.
|
||||
- The job workspace `Correspondence` tab shows ranked Gmail suggestions with match reasons/confidence, keeps a manual search override, and refreshes the visible job-linked correspondence list after import or linked-thread sync.
|
||||
|
||||
## Proof Level
|
||||
|
||||
@@ -21,21 +23,22 @@ S01 directly advances active requirements **R001** and **R002**, and it also lay
|
||||
|
||||
- `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`
|
||||
- Failure-path inspection: hit `api/gmail/status` while disconnected and exercise the job-scoped Gmail matching endpoint with an invalid or inaccessible `jobApplicationId`; confirm the API exposes connection state plus a clear `Job application not found.` or validation error response without leaking Gmail content.
|
||||
- Manual UAT: run the app, connect a real Gmail account, open one job in the workspace, confirm ranked Gmail suggestions appear before manual search, import one message and one full thread, and verify the imported correspondence appears on that same job with duplicates skipped and no send/apply automation.
|
||||
- Failure-path inspection: hit `api/gmail/status` while disconnected; exercise the job-scoped Gmail matching endpoint with an invalid or inaccessible `jobApplicationId`; and exercise the linked-thread refresh path with an unknown thread id or stale sync cursor. Confirm the API exposes connection state plus clear validation/not-found errors without leaking Gmail content.
|
||||
- Manual UAT: run the app, connect a real Gmail account, open one job in the workspace, confirm ranked Gmail suggestions appear before manual search, import one message and one full thread, send or receive another reply in Gmail on that linked thread, and verify the new reply appears on that same job without a manual re-import step and without any auto-send behavior.
|
||||
|
||||
## Observability / Diagnostics
|
||||
|
||||
- Runtime signals: ranked match reasons/confidence returned per candidate, import result counts for imported/skipped messages, and existing request logs with trace ids around Gmail endpoints.
|
||||
- Inspection surfaces: `api/gmail/status`, the new job-scoped Gmail matching response in `JobTrackerApi/Controllers/GmailController.cs`, the correspondence list in `job-tracker-ui/src/components/Correspondence.tsx`, and backend/frontend tests covering duplicate and failure paths.
|
||||
- Failure visibility: Gmail connection state, empty/noisy candidate lists, duplicate-skip counts, and per-candidate imported/already-linked flags should remain visible enough to tell whether failure came from query construction, Gmail retrieval, dedupe, or UI wiring.
|
||||
- Redaction constraints: never expose OAuth tokens or full message bodies in logs; diagnostics should stay at message metadata, ranking reasons, and import counts.
|
||||
- Runtime signals: ranked match reasons/confidence returned per candidate, import result counts for imported/skipped messages, linked-thread sync result counts, newest synced Gmail history marker/cursor per linked thread, and existing request logs with trace ids around Gmail endpoints.
|
||||
- Inspection surfaces: `api/gmail/status`, the job-scoped Gmail matching and linked-thread refresh responses in `JobTrackerApi/Controllers/GmailController.cs`, any Gmail sync/background service introduced for linked threads, the correspondence list in `job-tracker-ui/src/components/Correspondence.tsx`, and backend/frontend tests covering duplicate and sync failure paths.
|
||||
- Failure visibility: Gmail connection state, empty/noisy candidate lists, duplicate-skip counts, stale thread-sync state, and per-candidate imported/already-linked flags should remain visible enough to tell whether failure came from query construction, Gmail retrieval, dedupe, sync cursor handling, or UI wiring.
|
||||
- Redaction constraints: never expose OAuth tokens or full message bodies in logs; diagnostics should stay at message metadata, ranking reasons, sync counts, and import results.
|
||||
|
||||
## Integration Closure
|
||||
|
||||
- Upstream surfaces consumed: `JobTrackerApi/Services/GmailOAuthService.cs`, `Data/JobTrackerContext.cs`, `Models/JobApplication.cs`, `Models/Company.cs`, `Models/Correspondence.cs`, `job-tracker-ui/src/components/JobDetailsDialog.tsx`, and `job-tracker-ui/src/components/Correspondence.tsx`.
|
||||
- New wiring introduced in this slice: a job-aware Gmail candidate contract in the API, correspondence persistence that retains Gmail thread/message identity, and job-context-driven rendering in the workspace Gmail import UI.
|
||||
- What remains before the milestone is truly usable end-to-end: later slices still need to consume the imported correspondence for stronger drafting and daily workflow surfaces, but Gmail import itself should be trustworthy after this slice.
|
||||
- Additional wiring now required by the override: a linked-thread refresh mechanism that can detect new Gmail replies for already-imported threads and merge them into the job’s correspondence timeline without forcing the user to re-run import manually.
|
||||
- What remains before the milestone is truly usable end-to-end: later slices still need to consume the imported correspondence for stronger drafting and daily workflow surfaces, but Gmail import itself must now be trustworthy both at first import and during ongoing thread updates.
|
||||
|
||||
## Tasks
|
||||
|
||||
@@ -57,6 +60,18 @@ S01 directly advances active requirements **R001** and **R002**, and it also lay
|
||||
- Do: Pass job context from `JobDetailsDialog` into `Correspondence`, replace client-side primary ranking with the server-provided candidate contract, show match reasons/confidence/import state and thread actions, keep manual query/search as a fallback override, and add a React test that proves ranked suggestions and import refresh behavior in the dialog.
|
||||
- Verify: `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Done when: the Correspondence Gmail tab opens on ranked job-aware suggestions, still supports manual search overrides, refreshes the correspondence list after import, and the new UI test passes.
|
||||
- [ ] **T04: Add linked-thread refresh so imported Gmail threads stay current** `est:4h`
|
||||
- Why: The user’s trust bar is no longer just “can I import the right thread once?” but “does that thread continue to reflect reality after I reply or receive another response in Gmail?”
|
||||
- Files: `JobTrackerApi/Controllers/GmailController.cs`, `JobTrackerApi/Services/GmailOAuthService.cs`, `JobTrackerApi/Program.cs`, `Models/Correspondence.cs`, `JobTrackerApi.Tests/GmailControllerTests.cs`
|
||||
- Do: Add a linked-thread refresh path that can pull new Gmail messages for already-imported job threads using stored Gmail thread/message identity, dedupe against existing correspondence, import newly discovered inbound and sent replies into the same job, and expose enough sync status for the UI to know whether the thread is current.
|
||||
- Verify: `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests`
|
||||
- Done when: an already-linked Gmail thread can be refreshed without manual re-import, new sent/inbound replies land as correspondence on the same job, and focused tests prove dedupe plus stale-thread handling.
|
||||
- [ ] **T05: Surface automatic Gmail thread continuity in the workspace UI** `est:3h`
|
||||
- Why: Even with backend sync, the slice will still feel broken if the user cannot tell that a linked thread is auto-updating or whether a newly sent Gmail reply has already been incorporated.
|
||||
- Files: `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`
|
||||
- Do: Update the Correspondence tab to distinguish one-time suggestions from already-linked live threads, show last-sync or updating state, trigger automatic refresh on load and after manual job actions where appropriate, and extend the React test so a newly synced Gmail reply appears in the job correspondence list without a fresh import flow.
|
||||
- Verify: `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`
|
||||
- Done when: the user can see that a thread is linked/live, newly synced replies appear in the workspace automatically or on lightweight refresh, and the UI test covers the no-manual-reimport continuity path.
|
||||
|
||||
## Files Likely Touched
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"taskId": "T01",
|
||||
"unitId": "M001/S01/T01",
|
||||
"timestamp": 1774350445753,
|
||||
"passed": true,
|
||||
"discoverySource": "none",
|
||||
"checks": []
|
||||
}
|
||||
Reference in New Issue
Block a user