From 9a10df69fed4060fd1910444d0fefa8ac5b55a09 Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 24 Mar 2026 09:21:45 +0100 Subject: [PATCH] chore(M001/S01): auto-commit after research-slice --- .bg-shell/manifest.json | 1 + .gsd/DECISIONS.md | 13 + .gsd/PROJECT.md | 28 ++ .gsd/REQUIREMENTS.md | 239 ++++++++++++++++++ .gsd/journal/2026-03-24.jsonl | 4 + .gsd/milestones/M001/M001-CONTEXT.md | 113 +++++++++ .gsd/milestones/M001/M001-DISCUSSION.md | 40 +++ .gsd/milestones/M001/M001-META.json | 3 + .gsd/milestones/M001/M001-ROADMAP.md | 124 +++++++++ .../M001/slices/S01/S01-RESEARCH.md | 110 ++++++++ .gsd/milestones/M002/M002-CONTEXT-DRAFT.md | 42 +++ .gsd/milestones/M003/M003-CONTEXT-DRAFT.md | 41 +++ .gsd/milestones/M004/M004-CONTEXT-DRAFT.md | 41 +++ 13 files changed, 799 insertions(+) create mode 100644 .bg-shell/manifest.json create mode 100644 .gsd/DECISIONS.md create mode 100644 .gsd/PROJECT.md create mode 100644 .gsd/REQUIREMENTS.md create mode 100644 .gsd/journal/2026-03-24.jsonl create mode 100644 .gsd/milestones/M001/M001-CONTEXT.md create mode 100644 .gsd/milestones/M001/M001-DISCUSSION.md create mode 100644 .gsd/milestones/M001/M001-META.json create mode 100644 .gsd/milestones/M001/M001-ROADMAP.md create mode 100644 .gsd/milestones/M001/slices/S01/S01-RESEARCH.md create mode 100644 .gsd/milestones/M002/M002-CONTEXT-DRAFT.md create mode 100644 .gsd/milestones/M003/M003-CONTEXT-DRAFT.md create mode 100644 .gsd/milestones/M004/M004-CONTEXT-DRAFT.md diff --git a/.bg-shell/manifest.json b/.bg-shell/manifest.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/.bg-shell/manifest.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.gsd/DECISIONS.md b/.gsd/DECISIONS.md new file mode 100644 index 0000000..f5e4d8b --- /dev/null +++ b/.gsd/DECISIONS.md @@ -0,0 +1,13 @@ +# Decisions Register + + + +| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By | +|---|------|-------|----------|--------|-----------|------------|---------| +| D001 | M001 | scope | Product entry point | External job discovery, then import into the app | The user finds jobs on job sites first; the app begins when a role is imported. | No | collaborative | +| D002 | M001 | pattern | AI action model | Assistive drafting and analysis only; no autonomous sending | The user wants AI help but explicitly does not want auto-send or auto-apply behavior. | No | collaborative | +| D003 | M001 | scope | Primary user | Individual job seeker | The product is designed for individuals managing their own search, not recruiter or team workflows. | Yes — if product direction changes later | collaborative | +| D004 | M001 | pattern | Daily navigation hierarchy | Job table first, then follow-up/dashboard, then individual job workspace | The user explicitly described this as the intended control flow for daily use. | Yes — if real usage disproves the hierarchy | collaborative | +| D005 | M001 | roadmap | First milestone focus | Prioritize Gmail import quality and AI draft quality before broader expansion | The user identified Gmail import and AI drafts as the weakest current areas and the first bar for daily use. | Yes — if execution proves another blocker is more fundamental | collaborative | diff --git a/.gsd/PROJECT.md b/.gsd/PROJECT.md new file mode 100644 index 0000000..5d689c7 --- /dev/null +++ b/.gsd/PROJECT.md @@ -0,0 +1,28 @@ +# Project + +## What This Is + +Job Tracker is a personal job-application workspace for an individual user. The user finds jobs elsewhere, imports them into the app, uses AI to improve CVs, cover letters, replies, and follow-ups, and keeps the real-world application process organized through tracking, correspondence, and manual updates. + +## Core Value + +The product must let one person run a real job search without losing the thread: import a role, prepare stronger application material, track what happened, and know exactly what needs follow-up next. + +## Current State + +A substantial brownfield app already exists. The repo has a React frontend, an ASP.NET Core API, and a local FastAPI AI service. Current capabilities already include job tracking, companies, attachments, correspondence, reminders, job import preview, Gmail connection/import, profile CV upload/parsing/rewrite flows, AI-assisted tailored CV and cover-letter generation, candidate-fit/focus-plan/interview-prep/readiness endpoints, and dashboard/system surfaces. The next phase is not greenfield feature invention; it is turning existing capability into a more coherent, more trustworthy daily workflow. + +## Architecture / Key Patterns + +The frontend lives in `job-tracker-ui/` and is a React + TypeScript app using MUI. The backend lives in `JobTrackerApi/` and is an ASP.NET Core API with EF Core, Identity, background hosted services, and controller-based endpoints. The local AI service lives in `tools/summarizer/` and provides summarization plus OCR/text extraction. Existing patterns already center around per-job workspaces, Gmail-backed correspondence import, profile-CV-as-source-of-truth, attachment-level AI inclusion controls, and server-side generation endpoints that return drafts for user review rather than autonomous sending. + +## Capability Contract + +See `.gsd/REQUIREMENTS.md` for the explicit capability contract, requirement status, and coverage mapping. + +## Milestone Sequence + +- [ ] M001: Gmail and draft quality loop — Make Gmail import and AI drafting strong enough to trust as a daily workflow. +- [ ] M002: Tracking control center — Strengthen the job table, follow-up surfaces, and tracking rhythm into a clearer control center. +- [ ] M003: Deeper inbox-aware assistance — Extend correspondence awareness and context-driven assistance beyond the first Gmail improvements. +- [ ] M004: Trust, launchability, and hardening — Polish validation, clarity, performance, and operational trust surfaces for sustained daily use. diff --git a/.gsd/REQUIREMENTS.md b/.gsd/REQUIREMENTS.md new file mode 100644 index 0000000..47428a5 --- /dev/null +++ b/.gsd/REQUIREMENTS.md @@ -0,0 +1,239 @@ +# Requirements + +This file is the explicit capability and coverage contract for the project. + +Use it to track what is actively in scope, what has been validated by completed work, what is intentionally deferred, and what is explicitly out of scope. + +Guidelines: +- Keep requirements capability-oriented, not a giant feature wishlist. +- Requirements should be atomic, testable, and stated in plain language. +- Every **Active** requirement should be mapped to a slice, deferred, blocked with reason, or moved out of scope. +- Each requirement should have one accountable primary owner and may have supporting slices. +- Research may suggest requirements, but research does not silently make them binding. +- Validation means the requirement was actually proven by completed work and verification, not just discussed. + +## Active + +### R001 — External job import starts the workflow +- Class: primary-user-loop +- Status: active +- Description: The user finds a job outside the app, imports it into the app, and starts the application workflow from that imported role. +- Why it matters: The product is not a job board replacement; the import step is the real start of the user loop. +- Source: user +- Primary owning slice: M001/S01 +- Supporting slices: M001/S05 +- Validation: mapped +- Notes: This is a hard product-shape requirement, not a convenience feature. + +### R002 — Gmail import feels smart enough to trust +- Class: integration +- Status: active +- Description: Gmail connection, message retrieval, and message/thread import must help the user pull real correspondence into the right job with materially less manual cleanup. +- Why it matters: Gmail import is one of the two clearest current weaknesses and a major trust surface for daily use. +- Source: user +- Primary owning slice: M001/S01 +- Supporting slices: M001/S03, M001/S05 +- Validation: mapped +- Notes: Matching quality and import clarity matter more than merely exposing the API surface. + +### R003 — AI application drafts are materially useful +- Class: differentiator +- Status: active +- Description: Tailored CV and cover-letter drafts must feel specific, credible, and good enough that the user wants to start from them. +- Why it matters: Draft generation exists already, but the milestone bar is actual usefulness rather than feature presence. +- Source: user +- Primary owning slice: M001/S02 +- Supporting slices: M001/S05 +- Validation: mapped +- Notes: “A really good AI draft” is an explicit milestone success bar from the discussion. + +### R004 — Follow-up and reply drafts use real context +- Class: primary-user-loop +- Status: active +- Description: The app must generate follow-up and reply drafts from the imported job, saved application material, and correspondence context tied to that job. +- Why it matters: Follow-through is part of the core value, not an optional afterthought. +- Source: user +- Primary owning slice: M001/S03 +- Supporting slices: M001/S01, M001/S02, M001/S05 +- Validation: mapped +- Notes: The user stays in control of sending; the app provides strong drafts only. + +### R005 — Job table is the primary daily control surface +- Class: continuity +- Status: active +- Description: The first page should give the user a clear overview of jobs, status, readiness, and what needs attention. +- Why it matters: The user explicitly wants to start from the job table each day. +- Source: user +- Primary owning slice: M001/S04 +- Supporting slices: M001/S05 +- Validation: mapped +- Notes: This should feel like “scan the field” before drilling into one job. + +### R006 — Follow-up/dashboard surfaces the right urgency +- Class: continuity +- Status: active +- Description: The dashboard and follow-up surfaces must clearly show next actions, neglected threads, and jobs that need attention now. +- Why it matters: Tracking is only valuable if it turns state into action. +- Source: user +- Primary owning slice: M001/S04 +- Supporting slices: M001/S05 +- Validation: mapped +- Notes: The follow-up/dashboard view is the second navigation priority after the table. + +### R007 — Individual job workspace supports focused execution +- Class: core-capability +- Status: active +- Description: Each job needs a workspace where the user can update status, review/import correspondence, edit drafts, and prepare follow-ups. +- Why it matters: The user’s third step in the daily flow is to drop into a specific job and do focused work. +- Source: inferred +- Primary owning slice: M001/S03 +- Supporting slices: M001/S02, M001/S04 +- Validation: mapped +- Notes: This is where the product should feel connected instead of scattered. + +### R008 — Outbound actions remain manual and user-controlled +- Class: constraint +- Status: active +- Description: The app may draft application, reply, and follow-up content, but it must not auto-send emails or auto-apply to jobs. +- Why it matters: The user called auto-sending dangerous and explicitly does not want that behavior. +- Source: user +- Primary owning slice: M001/S03 +- Supporting slices: M001/S05 +- Validation: mapped +- Notes: This is a durable trust constraint across all milestones. + +### R009 — Product is designed for an individual, not a team workflow +- Class: constraint +- Status: active +- Description: Core UX, data model emphasis, and roadmap decisions should optimize for one person managing their own search. +- Why it matters: Individual-first scope keeps product decisions sharp and prevents premature recruiter/CRM drift. +- Source: user +- Primary owning slice: M001/S04 +- Supporting slices: M002/S01, M004/S01 +- Validation: mapped +- Notes: Shared/team workflows are not the current product target. + +### R010 — Tracking continuity survives manual and imported updates +- Class: continuity +- Status: active +- Description: The app must preserve a coherent history across manual status changes, imported Gmail correspondence, reminders, and follow-up work. +- Why it matters: The product promise is to keep the thread of the job search intact over time. +- Source: user +- Primary owning slice: M001/S04 +- Supporting slices: M001/S01, M001/S03, M001/S05 +- Validation: mapped +- Notes: This is part of what makes the app a tracker and follow-up system, not just a draft generator. + +## Validated + +None yet. + +## Deferred + +### R011 — Stronger tracking control-center analytics +- Class: operability +- Status: deferred +- Description: The app should later expand overview analytics, saved views, and clearer strategy readouts beyond the core daily loop. +- Why it matters: This can improve search strategy, but it is not the first trust gap to close. +- Source: inferred +- Primary owning slice: M002/S02 +- Supporting slices: none +- Validation: unmapped +- Notes: Deferred because Gmail import and draft quality are higher-value first fixes. + +### R012 — Broader inbox-aware assistance beyond initial Gmail improvements +- Class: integration +- Status: deferred +- Description: The product may later add richer message understanding, smarter thread handling, and broader inbox-aware assistance after the first Gmail milestone. +- Why it matters: This extends the correspondence workflow, but it depends on getting the initial import/matching loop right first. +- Source: inferred +- Primary owning slice: M003/S01 +- Supporting slices: none +- Validation: unmapped +- Notes: This is the natural next step after M001 proves the core Gmail path. + +### R013 — Richer AI coaching beyond the application/follow-up core +- Class: differentiator +- Status: deferred +- Description: The app may later add broader strategic coaching and more advanced guidance beyond application package and follow-up/reply drafting. +- Why it matters: There is room to deepen the assistant, but the current product bar is a stronger core workflow. +- Source: inferred +- Primary owning slice: M003/S02 +- Supporting slices: none +- Validation: unmapped +- Notes: Deferred to avoid scattering the first milestone. + +## Out of Scope + +### R014 — Auto-apply to jobs +- Class: anti-feature +- Status: out-of-scope +- Description: The app will not automatically submit applications to external job sites. +- Why it matters: This prevents product drift into risky, low-trust automation the user explicitly does not want. +- Source: user +- Primary owning slice: none +- Supporting slices: none +- Validation: n/a +- Notes: The app starts after discovery/import, not at job search submission. + +### R015 — Auto-send outbound email or messages +- Class: anti-feature +- Status: out-of-scope +- Description: The app will not send replies, follow-ups, or other communication autonomously. +- Why it matters: Manual control over outbound communication is a hard trust requirement. +- Source: user +- Primary owning slice: none +- Supporting slices: none +- Validation: n/a +- Notes: Drafting is allowed; autonomous sending is not. + +### R016 — Recruiter CRM or team collaboration workflows +- Class: out-of-scope +- Status: out-of-scope +- Description: The product will not optimize for shared pipelines, recruiter operations, or multi-user coaching workflows right now. +- Why it matters: This protects the individual-first product shape. +- Source: user +- Primary owning slice: none +- Supporting slices: none +- Validation: n/a +- Notes: Multi-user admin surfaces may exist technically, but they are not the roadmap center. + +### R017 — In-app job discovery replacing job boards +- Class: out-of-scope +- Status: out-of-scope +- Description: The app will not try to replace external job boards as the main discovery surface. +- Why it matters: The user explicitly described a workflow that starts after finding the job elsewhere. +- Source: user +- Primary owning slice: none +- Supporting slices: none +- Validation: n/a +- Notes: Job import is the bridge from external discovery into the app. + +## Traceability + +| ID | Class | Status | Primary owner | Supporting | Proof | +|---|---|---|---|---|---| +| R001 | primary-user-loop | active | M001/S01 | M001/S05 | mapped | +| R002 | integration | active | M001/S01 | M001/S03, M001/S05 | mapped | +| R003 | differentiator | active | M001/S02 | M001/S05 | mapped | +| R004 | primary-user-loop | active | M001/S03 | M001/S01, M001/S02, M001/S05 | mapped | +| R005 | continuity | active | M001/S04 | M001/S05 | mapped | +| R006 | continuity | active | M001/S04 | M001/S05 | mapped | +| R007 | core-capability | active | M001/S03 | M001/S02, M001/S04 | mapped | +| R008 | constraint | active | M001/S03 | M001/S05 | mapped | +| R009 | constraint | active | M001/S04 | M002/S01, M004/S01 | mapped | +| R010 | continuity | active | M001/S04 | M001/S01, M001/S03, M001/S05 | mapped | +| R011 | operability | deferred | M002/S02 | none | unmapped | +| R012 | integration | deferred | M003/S01 | none | unmapped | +| R013 | differentiator | deferred | M003/S02 | none | unmapped | +| R014 | anti-feature | out-of-scope | none | none | n/a | +| R015 | anti-feature | out-of-scope | none | none | n/a | +| R016 | out-of-scope | out-of-scope | none | none | n/a | +| R017 | out-of-scope | out-of-scope | none | none | n/a | + +## Coverage Summary + +- Active requirements: 10 +- Mapped to slices: 10 +- Validated: 0 +- Unmapped active requirements: 0 diff --git a/.gsd/journal/2026-03-24.jsonl b/.gsd/journal/2026-03-24.jsonl new file mode 100644 index 0000000..0fb86e3 --- /dev/null +++ b/.gsd/journal/2026-03-24.jsonl @@ -0,0 +1,4 @@ +{"ts":"2026-03-24T08:18:12.420Z","flowId":"80cd8f39-4c60-4e08-98bb-5b177f964592","seq":1,"eventType":"iteration-start","data":{"iteration":1}} +{"ts":"2026-03-24T08:18:12.498Z","flowId":"80cd8f39-4c60-4e08-98bb-5b177f964592","seq":2,"eventType":"dispatch-match","rule":"planning (no research, not S01) → research-slice","data":{"unitType":"research-slice","unitId":"M001/S01"}} +{"ts":"2026-03-24T08:18:12.504Z","flowId":"80cd8f39-4c60-4e08-98bb-5b177f964592","seq":3,"eventType":"unit-start","data":{"unitType":"research-slice","unitId":"M001/S01"}} +{"ts":"2026-03-24T08:21:44.843Z","flowId":"80cd8f39-4c60-4e08-98bb-5b177f964592","seq":4,"eventType":"unit-end","data":{"unitType":"research-slice","unitId":"M001/S01","status":"completed","artifactVerified":true},"causedBy":{"flowId":"80cd8f39-4c60-4e08-98bb-5b177f964592","seq":3}} diff --git a/.gsd/milestones/M001/M001-CONTEXT.md b/.gsd/milestones/M001/M001-CONTEXT.md new file mode 100644 index 0000000..467cca5 --- /dev/null +++ b/.gsd/milestones/M001/M001-CONTEXT.md @@ -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 diff --git a/.gsd/milestones/M001/M001-DISCUSSION.md b/.gsd/milestones/M001/M001-DISCUSSION.md new file mode 100644 index 0000000..7be79a7 --- /dev/null +++ b/.gsd/milestones/M001/M001-DISCUSSION.md @@ -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) + +--- diff --git a/.gsd/milestones/M001/M001-META.json b/.gsd/milestones/M001/M001-META.json new file mode 100644 index 0000000..b657e91 --- /dev/null +++ b/.gsd/milestones/M001/M001-META.json @@ -0,0 +1,3 @@ +{ + "integrationBranch": "main" +} diff --git a/.gsd/milestones/M001/M001-ROADMAP.md b/.gsd/milestones/M001/M001-ROADMAP.md new file mode 100644 index 0000000..70c539e --- /dev/null +++ b/.gsd/milestones/M001/M001-ROADMAP.md @@ -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 diff --git a/.gsd/milestones/M001/slices/S01/S01-RESEARCH.md b/.gsd/milestones/M001/slices/S01/S01-RESEARCH.md new file mode 100644 index 0000000..615c440 --- /dev/null +++ b/.gsd/milestones/M001/slices/S01/S01-RESEARCH.md @@ -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 | diff --git a/.gsd/milestones/M002/M002-CONTEXT-DRAFT.md b/.gsd/milestones/M002/M002-CONTEXT-DRAFT.md new file mode 100644 index 0000000..ed970d0 --- /dev/null +++ b/.gsd/milestones/M002/M002-CONTEXT-DRAFT.md @@ -0,0 +1,42 @@ +--- +depends_on: [M001] +--- + +# M002: Tracking control center — Context Draft + +**Gathered:** 2026-03-24 +**Status:** Draft — needs milestone-specific discussion before planning + +## Seed from broader discussion + +The product should feel first like a tracker and follow-up system, not just a collection of AI tools. The agreed navigation hierarchy is job table first, then follow-up/dashboard, then individual job workspace. That means M002 is the milestone where the tracking and control-center surfaces likely get stronger after M001 proves Gmail import quality and AI draft quality. + +## Intended milestone role + +M002 likely expands the app from “good Gmail + good drafts” into a clearer job-search control center for an individual user. The likely emphasis is better table/dashboard/follow-up workflow, better visibility into what needs action, and stronger continuity through the life of each application. + +## Likely capabilities + +- stronger table views and status clarity +- better follow-up/dashboard action surfacing +- tighter tracking continuity across manual updates and imported correspondence +- clearer operating rhythm for daily use +- likely analytics/pattern visibility only where it directly improves decision-making + +## Constraints already known + +- individual-first product shape remains in force +- no auto-send or auto-apply behavior +- job discovery still happens outside the app +- table → follow-up/dashboard → job workspace remains the intended daily navigation hierarchy unless usage disproves it + +## What this milestone unlocks + +A version of the product that feels more like the user’s daily control center and less like a set of helpful but disconnected screens. + +## Open questions for future discussion + +- How much of M002 should be action clarity versus analytics polish? +- Which table/dashboard views feel most lacking in current use? +- Should saved views, stronger filtering, or timeline/history clarity be core in this milestone? +- What specific “I know what to do next” experience should the dashboard deliver every morning? diff --git a/.gsd/milestones/M003/M003-CONTEXT-DRAFT.md b/.gsd/milestones/M003/M003-CONTEXT-DRAFT.md new file mode 100644 index 0000000..d8cace7 --- /dev/null +++ b/.gsd/milestones/M003/M003-CONTEXT-DRAFT.md @@ -0,0 +1,41 @@ +--- +depends_on: [M001, M002] +--- + +# M003: Deeper inbox-aware assistance — Context Draft + +**Gathered:** 2026-03-24 +**Status:** Draft — needs milestone-specific discussion before planning + +## Seed from broader discussion + +After the first Gmail improvements, there is likely room to deepen inbox-aware assistance and correspondence-driven help. This should still remain assistive rather than autonomous, and it should continue to support an individual user’s job-search workflow instead of turning into broad automation for its own sake. + +## Intended milestone role + +M003 likely extends the correspondence and assistance layer beyond the first trust milestone. The likely focus is richer inbox awareness, better use of message context over time, and additional AI help that stays grounded in real application history. + +## Likely capabilities + +- richer message/thread understanding after import +- better context assembly from accumulated correspondence +- broader assistance around replies, follow-up strategy, and ongoing job-specific communication +- selective expansion of AI coaching only where it strengthens the core user loop + +## Constraints already known + +- no auto-send and no auto-apply remain hard boundaries +- assistance should stay grounded in imported job/application/correspondence context +- the product is still for one person managing their own search +- the app should not drift into generic chatbot behavior + +## What this milestone unlocks + +A more aware assistant that understands the state of an application thread over time and can help the user respond more intelligently without taking control away. + +## Open questions for future discussion + +- What additional inbox-aware behavior is actually high value after M001? +- How much strategic coaching belongs here versus later? +- Which parts of correspondence history should influence drafting most? +- What privacy or trust surfaces need to become more visible as the assistant becomes more context-aware? diff --git a/.gsd/milestones/M004/M004-CONTEXT-DRAFT.md b/.gsd/milestones/M004/M004-CONTEXT-DRAFT.md new file mode 100644 index 0000000..29949b6 --- /dev/null +++ b/.gsd/milestones/M004/M004-CONTEXT-DRAFT.md @@ -0,0 +1,41 @@ +--- +depends_on: [M001, M002, M003] +--- + +# M004: Trust, launchability, and hardening — Context Draft + +**Gathered:** 2026-03-24 +**Status:** Draft — needs milestone-specific discussion before planning + +## Seed from broader discussion + +The app already has meaningful breadth: auth, Gmail integration, AI service integration, drafting, reminders, imports, dashboards, and admin/system pages. Once the core workflow is strong enough, the next need is likely hardening: making the product clearer, safer, more diagnosable, and easier to live with over time. + +## Intended milestone role + +M004 likely focuses on trust, clarity, and operational hardening after the core workflow is proven. This includes the quality of validation, clarity of failure modes, performance, launch readiness, and operational confidence for a product used repeatedly during a real job search. + +## Likely capabilities + +- clearer validation and failure visibility +- UX and terminology cleanup where the product still feels messy or inconsistent +- performance and reliability improvements around key surfaces +- stronger operational/admin clarity for self-hosted or deployed use +- final trust surfaces around how AI and integrations behave + +## Constraints already known + +- the product must preserve manual control over outbound communication +- hardening should support the individual-first workflow rather than introducing enterprise complexity +- changes should build on the existing architecture rather than force a platform rewrite + +## What this milestone unlocks + +A product that not only has the right workflow, but also feels solid, comprehensible, and trustworthy enough for sustained daily use and future expansion. + +## Open questions for future discussion + +- Which hardening gaps are most painful in actual use by the time this milestone arrives? +- What launchability bar matters for this project: self-hosted personal use, broader deployment, or something in between? +- Which trust/diagnostic surfaces are most important for AI-assisted correspondence and drafting? +- What level of polish is necessary before the product feels genuinely finished rather than just feature-complete?