bdc47dde7f
GSD-Unit: M001/S06/T01
834 lines
42 KiB
JSON
834 lines
42 KiB
JSON
{
|
||
"version": 1,
|
||
"exported_at": "2026-03-27T07:47:00.101Z",
|
||
"milestones": [
|
||
{
|
||
"id": "M001",
|
||
"title": "M001: Gmail and draft quality loop",
|
||
"status": "active",
|
||
"depends_on": [],
|
||
"created_at": "2026-03-27T07:30:18.608Z",
|
||
"completed_at": null,
|
||
"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 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": [],
|
||
"proof_strategy": [],
|
||
"verification_contract": "",
|
||
"verification_integration": "",
|
||
"verification_operational": "",
|
||
"verification_uat": "",
|
||
"definition_of_done": [],
|
||
"requirement_coverage": "",
|
||
"boundary_map_markdown": "## Boundary Map\n\n### S01 → S02\n\nProduces:\n- improved Gmail import workflow in `job-tracker-ui/src/components/Correspondence.tsx` that yields job-linked imported correspondence with clearer message/thread selection behavior\n- stronger backend correspondence import surface in `JobTrackerApi/Controllers/GmailController.cs` and related persistence so imported messages reliably attach to `JobApplication` records\n- linked-thread metadata and refresh behavior stable enough that later draft-generation flows can consume correspondence as trusted context rather than a stale snapshot\n\nConsumes:\n- nothing (first slice)\n\n### S01 → S03\n\nProduces:\n- imported correspondence records tied to a specific job and available through the existing per-job correspondence/timeline surfaces\n- message/thread metadata good enough for later reply/follow-up draft context assembly\n- a verified Gmail connection/import path that downstream slices can rely on, including ongoing thread refresh after first import\n\nConsumes:\n- nothing (first slice)\n\n### S02 → S03\n\nProduces:\n- improved application package generation via `JobTrackerApi/Controllers/JobApplicationsController.cs` returning stronger tailored CV and cover-letter outputs tied to a job\n- persisted draft state in the job workspace so later follow-up/reply flows can reuse saved application context\n- clearer frontend editing/saving behavior in `job-tracker-ui/src/components/JobDetailsDialog.tsx`\n\nConsumes from S01:\n- imported and auto-refreshed correspondence plus job-linked message context\n\n### S03 → S04\n\nProduces:\n- reply/follow-up draft flow grounded in job + correspondence + saved application package context\n- explicit manual-send boundary in the job workspace UI and backend behavior\n- job-level indicators that a follow-up/reply is ready, missing context, or needs action\n\nConsumes from S01:\n- Gmail-imported and automatically refreshed correspondence context\n\nConsumes from S02:\n- saved tailored CV / cover-letter / application package context\n\n### S04 → S05\n\nProduces:\n- table/dashboard surfaces that summarize readiness, follow-up urgency, and next actions for individual users\n- clearer navigation hierarchy across table, follow-up/dashboard, and individual job workspace\n- stable daily-use control loop to validate in final integration\n\nConsumes from S01:\n- correspondence state, Gmail import outcomes, and linked-thread refresh outcomes\n\nConsumes from S03:\n- follow-up/reply drafting signals and job-level action state"
|
||
},
|
||
{
|
||
"id": "M002",
|
||
"title": "",
|
||
"status": "active",
|
||
"depends_on": [],
|
||
"created_at": "2026-03-27T07:30:18.632Z",
|
||
"completed_at": null,
|
||
"vision": "",
|
||
"success_criteria": [],
|
||
"key_risks": [],
|
||
"proof_strategy": [],
|
||
"verification_contract": "",
|
||
"verification_integration": "",
|
||
"verification_operational": "",
|
||
"verification_uat": "",
|
||
"definition_of_done": [],
|
||
"requirement_coverage": "",
|
||
"boundary_map_markdown": ""
|
||
},
|
||
{
|
||
"id": "M003",
|
||
"title": "",
|
||
"status": "active",
|
||
"depends_on": [],
|
||
"created_at": "2026-03-27T07:30:18.632Z",
|
||
"completed_at": null,
|
||
"vision": "",
|
||
"success_criteria": [],
|
||
"key_risks": [],
|
||
"proof_strategy": [],
|
||
"verification_contract": "",
|
||
"verification_integration": "",
|
||
"verification_operational": "",
|
||
"verification_uat": "",
|
||
"definition_of_done": [],
|
||
"requirement_coverage": "",
|
||
"boundary_map_markdown": ""
|
||
},
|
||
{
|
||
"id": "M004",
|
||
"title": "",
|
||
"status": "active",
|
||
"depends_on": [],
|
||
"created_at": "2026-03-27T07:30:18.632Z",
|
||
"completed_at": null,
|
||
"vision": "",
|
||
"success_criteria": [],
|
||
"key_risks": [],
|
||
"proof_strategy": [],
|
||
"verification_contract": "",
|
||
"verification_integration": "",
|
||
"verification_operational": "",
|
||
"verification_uat": "",
|
||
"definition_of_done": [],
|
||
"requirement_coverage": "",
|
||
"boundary_map_markdown": ""
|
||
}
|
||
],
|
||
"slices": [
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S01",
|
||
"title": "Smarter Gmail import and matching",
|
||
"status": "complete",
|
||
"risk": "high",
|
||
"depends": [],
|
||
"demo": "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.",
|
||
"created_at": "2026-03-27T07:30:18.611Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Finish S01 by turning the existing job-aware Gmail import flow into a live linked-thread continuity loop for one job workspace.",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S02",
|
||
"title": "Stronger AI application package drafting",
|
||
"status": "complete",
|
||
"risk": "high",
|
||
"depends": [
|
||
"S01"
|
||
],
|
||
"demo": "From an imported job plus profile/CV context, the app generates materially better tailored CV and cover-letter drafts that feel specific and usable.",
|
||
"created_at": "2026-03-27T07:30:18.613Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Make the application package generator use imported job/correspondence context well enough that tailored CV, cover-letter, and recruiter-message drafts feel specific, credible, and worth starting from inside the job workspace.",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S03",
|
||
"title": "Reply and follow-up drafting from real thread context",
|
||
"status": "complete",
|
||
"risk": "medium",
|
||
"depends": [
|
||
"S01",
|
||
"S02"
|
||
],
|
||
"demo": "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.",
|
||
"created_at": "2026-03-27T07:30:18.613Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Make follow-up drafting use imported correspondence and saved application material well enough that the job workspace can produce specific, trustworthy follow-up and reply drafts without crossing the manual-send boundary.",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S04",
|
||
"title": "Daily control loop surfaces",
|
||
"status": "complete",
|
||
"risk": "medium",
|
||
"depends": [
|
||
"S01",
|
||
"S03"
|
||
],
|
||
"demo": "The job table works as the primary overview and the follow-up/dashboard surfaces clearly show what needs attention next for an individual user.",
|
||
"created_at": "2026-03-27T07:30:18.615Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Make the job table, reminders view, and dashboard behave like one daily control loop so the user can scan what needs attention and jump directly into the right job workspace state.",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S05",
|
||
"title": "End-to-end trust and workflow polish",
|
||
"status": "complete",
|
||
"risk": "low",
|
||
"depends": [
|
||
"S01",
|
||
"S02",
|
||
"S03",
|
||
"S04"
|
||
],
|
||
"demo": "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.",
|
||
"created_at": "2026-03-27T07:30:18.616Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Prove the full daily-use loop as one trustworthy workflow by tightening shared next-action/readiness signals, then validating overview → workspace → package → Gmail continuity → follow-up behavior without weakening the manual-send boundary.",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S06",
|
||
"title": "Live environment stabilization and integrated acceptance rerun",
|
||
"status": "pending",
|
||
"risk": "high",
|
||
"depends": [
|
||
"S05"
|
||
],
|
||
"demo": "The real M001 environment runs without the current backend/frontend CORS/runtime blockage, and the full `/jobs` → workspace → Gmail continuity → follow-up → dashboard/reminders loop is re-checked live with recorded acceptance results.",
|
||
"created_at": "2026-03-27T07:30:18.617Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "Live environment is repeatably startable and preflighted, seeded with acceptance-ready data, and the integrated daily loop is re-verified with a recorded artifact proving the manual-send boundary and individual-first workflow.",
|
||
"success_criteria": "- Preflight gate confirms API/auth readiness, admin/system status, and Gmail configuration truthfully before any UI run.\n- Acceptance seed produces at least one job with saved package material, correspondence, and follow-up readiness so overview surfaces and workspace tabs show actionable state.\n- Integrated acceptance rerun is executed against the live stack, and results (passes/blocks) are captured in a committed artifact covering /jobs → workspace → reminders/dashboard → follow-up/manual-send boundary.",
|
||
"proof_level": "integration / operational — real runtime and browser walk required, with human/UAT notes when automation cannot cover.",
|
||
"integration_closure": "Upstream surfaces consumed: `JobTrackerApi/Program.cs`, `JobTrackerApi/appsettings.Development.json`, `/api/admin/system`, `/api/auth/config`, `/api/jobapplications*`, `/api/correspondence/{id}`, `/api/gmail/status`, `job-tracker-ui/src/api.ts`, overview/workspace components.\nNew wiring introduced: preflight + acceptance-data scripts to make runtime bring-up and seeding repeatable; acceptance run script + artifact tying overview entry and workspace tabs to live endpoints.\nRemaining for milestone end-to-end: S07 will turn the rerun into the final UAT artifact, but S06 must already deliver truthful live evidence and note any Gmail continuity gaps.",
|
||
"observability_impact": "Runtime signals: `/api/admin/system` fields (database/auth/gmailConfigured/ai health), `/api/auth/config` truthfulness, seeded job presence via `/api/jobapplications` and reminders/readiness endpoints.\nInspection surfaces: `scripts/s06-preflight.sh`, `scripts/s06-acceptance-data.sh`, `scripts/s06-acceptance-run.sh` outputs; browser UI states on /jobs, /dashboard, /reminders, workspace tabs.\nFailure visibility: each script should exit non-zero with clear message (missing token, API unreachable, seed failure); acceptance artifact must call out blocked checks explicitly.\nRedaction constraints: keep tokens/PII out of artifacts; use env vars for secrets (e.g., AUTH_TOKEN, GMAIL creds) and avoid logging raw tokens.",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"id": "S07",
|
||
"title": "Daily-loop UAT artifact closure",
|
||
"status": "pending",
|
||
"risk": "medium",
|
||
"depends": [
|
||
"S06"
|
||
],
|
||
"demo": "The overview-surface/browser validation is captured as a real executed UAT artifact instead of a placeholder, proving the same job behaves coherently across table, dashboard, reminders, and workspace entry.",
|
||
"created_at": "2026-03-27T07:30:18.617Z",
|
||
"completed_at": null,
|
||
"full_summary_md": "",
|
||
"full_uat_md": "",
|
||
"goal": "",
|
||
"success_criteria": "",
|
||
"proof_level": "",
|
||
"integration_closure": "",
|
||
"observability_impact": "",
|
||
"sequence": 0,
|
||
"replan_triggered_at": null
|
||
}
|
||
],
|
||
"tasks": [
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S01",
|
||
"id": "T01",
|
||
"title": "Add linked Gmail thread refresh to the backend contract",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.612Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"JobTrackerApi/Controllers/GmailController.cs",
|
||
"JobTrackerApi/Services/GmailOAuthService.cs",
|
||
"JobTrackerApi.Tests/GmailControllerTests.cs",
|
||
"JobTrackerApi/Program.cs"
|
||
],
|
||
"verify": "`dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S01",
|
||
"id": "T02",
|
||
"title": "Surface live Gmail thread continuity in the job workspace",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.612Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/Correspondence.tsx",
|
||
"job-tracker-ui/src/types.ts",
|
||
"job-tracker-ui/src/correspondence-gmail-import.test.tsx",
|
||
"job-tracker-ui/src/components/JobDetailsDialog.tsx"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S02",
|
||
"id": "T01",
|
||
"title": "Strengthen application-package context assembly and backend draft tests",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.613Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"JobTrackerApi/Controllers/JobApplicationsController.cs",
|
||
"JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs"
|
||
],
|
||
"verify": "`dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter JobApplicationsApplicationPackageTests`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S02",
|
||
"id": "T02",
|
||
"title": "Make the job workspace save and present the application package as real working material",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.613Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/JobDetailsDialog.tsx",
|
||
"job-tracker-ui/src/types.ts",
|
||
"job-tracker-ui/src/job-details-generated-drafts.test.tsx"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/job-details-generated-drafts.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S03",
|
||
"id": "T01",
|
||
"title": "Strengthen follow-up draft context assembly and backend reply/follow-up tests",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.613Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"JobTrackerApi/Controllers/JobApplicationsController.cs",
|
||
"JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs"
|
||
],
|
||
"verify": "`dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter JobApplicationsFollowUpDraftTests`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S03",
|
||
"id": "T02",
|
||
"title": "Make the follow-up workspace show thread-grounded draft state without autonomous sending",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.614Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/JobDetailsDialog.tsx",
|
||
"job-tracker-ui/src/types.ts",
|
||
"job-tracker-ui/src/job-details-followup-drafts.test.tsx"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/job-details-followup-drafts.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S04",
|
||
"id": "T01",
|
||
"title": "Turn reminders and dashboard into actionable entry surfaces",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.615Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/DashboardView.tsx",
|
||
"job-tracker-ui/src/components/RemindersView.tsx",
|
||
"job-tracker-ui/src/App.tsx"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/daily-control-loop.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S04",
|
||
"id": "T02",
|
||
"title": "Make the job table expose the right next action and prove the daily loop",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.615Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/JobTable.tsx",
|
||
"job-tracker-ui/src/daily-control-loop.test.tsx"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/daily-control-loop.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S05",
|
||
"id": "T01",
|
||
"title": "Centralize workflow trust signals across overview and readiness surfaces",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.616Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"JobTrackerApi/Controllers/JobApplicationsController.cs",
|
||
"JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs",
|
||
"job-tracker-ui/src/types.ts",
|
||
"job-tracker-ui/src/jobWorkflowSignals.ts",
|
||
"job-tracker-ui/src/components/JobTable.tsx",
|
||
"job-tracker-ui/src/components/DashboardView.tsx",
|
||
"job-tracker-ui/src/components/RemindersView.tsx",
|
||
"job-tracker-ui/src/workflow-trust-signals.test.tsx"
|
||
],
|
||
"verify": "`dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter JobApplicationsWorkflowSignalsTests` and `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/workflow-trust-signals.test.tsx`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S05",
|
||
"id": "T02",
|
||
"title": "Add integrated trust-loop proof and workspace polish",
|
||
"status": "complete",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": "2026-03-27T07:30:18.617Z",
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "",
|
||
"estimate": "",
|
||
"files": [
|
||
"job-tracker-ui/src/components/JobDetailsDialog.tsx",
|
||
"job-tracker-ui/src/components/Correspondence.tsx",
|
||
"job-tracker-ui/src/end-to-end-trust-loop.test.tsx",
|
||
"job-tracker-ui/src/daily-control-loop.test.tsx",
|
||
".gsd/milestones/M001/slices/S05/S05-UAT.md"
|
||
],
|
||
"verify": "`CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/end-to-end-trust-loop.test.tsx`, `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx src/job-details-generated-drafts.test.tsx src/job-details-followup-drafts.test.tsx src/daily-control-loop.test.tsx`, and `CI=true npm --prefix job-tracker-ui run build`",
|
||
"inputs": [],
|
||
"expected_output": [],
|
||
"observability_impact": "",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S06",
|
||
"id": "T01",
|
||
"title": "Add preflight gate for live API/auth readiness",
|
||
"status": "pending",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": null,
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "Build a repeatable preflight script and doc so environment blockers are caught before browser UAT.\n- Why: avoid the ERR_CONNECTION_REFUSED/CORS/auth mismatch that currently blocks the UI.\n- Steps:\n 1) Create `scripts/s06-preflight.sh` (bash, executable) that assumes backend already started; probes `/api/auth/config` and `/api/admin/system` on `http://localhost:5202/api`, printing database/auth/gmailConfigured/ai status and failing fast on unreachable endpoints.\n 2) Ensure script respects `API_BASE` env override and uses `curl -f` with readable errors; no secrets logged.\n 3) Add a short runbook snippet to `README.md` showing backend start command from `JobTrackerApi/` and how to run the preflight (including auth token note if required).\n 4) Sanity-check CORS expectations vs `job-tracker-ui/src/api.ts` and document the required origin pairing (UI :3000, API :5202).\n- Failure Modes (Q5): API down → exit 1 with hint to start API; Auth required without token → script notes auth required and how to obtain; malformed JSON → show raw body and fail.\n- Load Profile (Q6): trivial single-user curl calls; no scaling concern.\n- Negative Tests (Q7): run script with API stopped (expect non-zero); run with wrong `API_BASE` (expect clear error message).\n- Must-haves: preflight script exists/executable; README runbook mentions backend start + preflight; script outputs gmailConfigured/auth/db/ai fields.\n- Verification: `bash scripts/s06-preflight.sh`",
|
||
"estimate": "45m",
|
||
"files": [
|
||
"scripts/s06-preflight.sh",
|
||
"README.md",
|
||
"job-tracker-ui/src/api.ts",
|
||
"JobTrackerApi/appsettings.Development.json"
|
||
],
|
||
"verify": "bash scripts/s06-preflight.sh",
|
||
"inputs": [
|
||
"`JobTrackerApi/Program.cs`",
|
||
"`JobTrackerApi/appsettings.Development.json`",
|
||
"`job-tracker-ui/src/api.ts`",
|
||
"`README.md`"
|
||
],
|
||
"expected_output": [
|
||
"`scripts/s06-preflight.sh`",
|
||
"`README.md`"
|
||
],
|
||
"observability_impact": "Adds preflight status surface exposing DB/auth/gmail/ai readiness via curl; provides explicit failure messages for unreachable API/CORS/auth.",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S06",
|
||
"id": "T02",
|
||
"title": "Seed acceptance-ready job data",
|
||
"status": "pending",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": null,
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "Create a seed script that prepares a richer acceptance fixture (job, correspondence, saved package, follow-up readiness) using live API calls.\n- Why: current DB has only 1 low-signal job; acceptance rerun needs actionable overview + workspace state.\n- Steps:\n 1) Write `scripts/s06-acceptance-data.sh` (bash, executable) that requires `AUTH_TOKEN` env; uses `scripts/s06-preflight.sh` first, then POSTs to `/api/jobapplications` (or PUT existing ID) to create a job with saved package fields, correspondence entry, reminder/follow-up signals, and notes.\n 2) Add curl helpers for adding correspondence (`/api/correspondence/{jobId}` or equivalent), saving package material, and setting workflow/readiness if needed; use deterministic titles so rerun is idempotent (update if exists).\n 3) Emit a short summary of created/updated IDs so the acceptance run can target them; avoid logging token.\n 4) Document any manual token retrieval step in script comments.\n- Failure Modes (Q5): missing AUTH_TOKEN → fail with guidance; 401/403 → explain token issue; 5xx → print response and fail; malformed response → show body and fail.\n- Load Profile (Q6): few API calls; minimal DB impact.\n- Negative Tests (Q7): run without AUTH_TOKEN (expect failure); rerun twice (should succeed idempotently); simulate 401 by bad token (expect clear message).\n- Must-haves: script seeds at least one job with saved package + correspondence + follow-up readiness; outputs job id for UAT; uses preflight.\n- Verification: `bash scripts/s06-acceptance-data.sh`",
|
||
"estimate": "1h",
|
||
"files": [
|
||
"scripts/s06-acceptance-data.sh",
|
||
"scripts/s06-preflight.sh",
|
||
"README.md"
|
||
],
|
||
"verify": "bash scripts/s06-acceptance-data.sh",
|
||
"inputs": [
|
||
"`scripts/s06-preflight.sh`",
|
||
"`README.md`",
|
||
"`JobTrackerApi/Controllers/JobApplicationsController.cs`",
|
||
"`JobTrackerApi/Controllers/CorrespondenceController.cs`"
|
||
],
|
||
"expected_output": [
|
||
"`scripts/s06-acceptance-data.sh`",
|
||
"`README.md`"
|
||
],
|
||
"observability_impact": "Provides seed summary output (job id, correspondence count) to inspect readiness; failures surface via script exit and printed API responses.",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
},
|
||
{
|
||
"milestone_id": "M001",
|
||
"slice_id": "S06",
|
||
"id": "T03",
|
||
"title": "Run integrated acceptance and capture evidence",
|
||
"status": "pending",
|
||
"one_liner": "",
|
||
"narrative": "",
|
||
"verification_result": "",
|
||
"duration": "",
|
||
"completed_at": null,
|
||
"blocker_discovered": false,
|
||
"deviations": "",
|
||
"known_issues": "",
|
||
"key_files": [],
|
||
"key_decisions": [],
|
||
"full_summary_md": "",
|
||
"description": "Execute the live acceptance loop and record results as an artifact for S07/UAT handoff.\n- Why: prove the `/jobs → workspace → reminders/dashboard → follow-up/manual-send boundary` loop runs in the live stack after stabilization and seeding.\n- Steps:\n 1) Create `scripts/s06-acceptance-run.sh` to orchestrate: ensure backend running, run preflight + seed scripts, then run existing automated regressions most relevant to the loop (e.g., `end-to-end-trust-loop.test.tsx`) and capture outputs.\n 2) Perform a guided browser run (can use agent-browser/Playwright) hitting /jobs, /reminders, /dashboard, opening the seeded job workspace, inspecting Tailored CV, Correspondence (linked-thread status), Follow-up draft manual-send boundary; note Gmail continuity if blocked.\n 3) Write findings and screenshots/links into `docs/s06-acceptance-run.md` (what passed, what blocked, manual-send boundary observation, Gmail continuity status). Call out any gaps explicitly.\n 4) Ensure commands avoid leaking tokens; artifacts redact secrets.\n- Failure Modes (Q5): backend not running → script stops after preflight; tests fail → record failure in artifact; browser step blocked by auth → document and include auth instructions.\n- Load Profile (Q6): single-user flows; test runner CPU-bound but acceptable.\n- Negative Tests (Q7): note expected failure if Gmail remains unconfigured; ensure manual-send boundary not auto-triggered during run.\n- Must-haves: acceptance-run script exists; artifact populated with live results; manual-send boundary explicitly observed; Gmail continuity status recorded (even if blocked).\n- Verification: `bash scripts/s06-acceptance-run.sh` && `test -s docs/s06-acceptance-run.md`",
|
||
"estimate": "1h30m",
|
||
"files": [
|
||
"scripts/s06-acceptance-run.sh",
|
||
"docs/s06-acceptance-run.md",
|
||
"scripts/s06-preflight.sh",
|
||
"scripts/s06-acceptance-data.sh",
|
||
"job-tracker-ui/src/end-to-end-trust-loop.test.tsx"
|
||
],
|
||
"verify": "bash scripts/s06-acceptance-run.sh && test -s docs/s06-acceptance-run.md",
|
||
"inputs": [
|
||
"`scripts/s06-preflight.sh`",
|
||
"`scripts/s06-acceptance-data.sh`",
|
||
"`job-tracker-ui/src/end-to-end-trust-loop.test.tsx`",
|
||
"`job-tracker-ui/src/components/JobDetailsDialog.tsx`",
|
||
"`job-tracker-ui/src/components/Correspondence.tsx`"
|
||
],
|
||
"expected_output": [
|
||
"`scripts/s06-acceptance-run.sh`",
|
||
"`docs/s06-acceptance-run.md`"
|
||
],
|
||
"observability_impact": "Orchestrated run logs preflight/seed/test results; artifact captures UI observations incl. manual-send boundary and Gmail continuity. Scripts surface failures with exit codes and summarized outputs.",
|
||
"full_plan_md": "",
|
||
"sequence": 0
|
||
}
|
||
],
|
||
"decisions": [
|
||
{
|
||
"seq": 1,
|
||
"id": "D001",
|
||
"when_context": "M001",
|
||
"scope": "scope",
|
||
"decision": "Product entry point",
|
||
"choice": "External job discovery, then import into the app",
|
||
"rationale": "The user finds jobs on job sites first; the app begins when a role is imported.",
|
||
"revisable": "No",
|
||
"made_by": "collaborative",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 2,
|
||
"id": "D002",
|
||
"when_context": "M001",
|
||
"scope": "pattern",
|
||
"decision": "AI action model",
|
||
"choice": "Assistive drafting and analysis only; no autonomous sending",
|
||
"rationale": "The user wants AI help but explicitly does not want auto-send or auto-apply behavior.",
|
||
"revisable": "No",
|
||
"made_by": "collaborative",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 3,
|
||
"id": "D003",
|
||
"when_context": "M001",
|
||
"scope": "scope",
|
||
"decision": "Primary user",
|
||
"choice": "Individual job seeker",
|
||
"rationale": "The product is designed for individuals managing their own search, not recruiter or team workflows.",
|
||
"revisable": "Yes — if product direction changes later",
|
||
"made_by": "collaborative",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 4,
|
||
"id": "D004",
|
||
"when_context": "M001",
|
||
"scope": "pattern",
|
||
"decision": "Daily navigation hierarchy",
|
||
"choice": "Job table first, then follow-up/dashboard, then individual job workspace",
|
||
"rationale": "The user explicitly described this as the intended control flow for daily use.",
|
||
"revisable": "Yes — if real usage disproves the hierarchy",
|
||
"made_by": "collaborative",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 5,
|
||
"id": "D005",
|
||
"when_context": "M001",
|
||
"scope": "roadmap",
|
||
"decision": "First milestone focus",
|
||
"choice": "Prioritize Gmail import quality and AI draft quality before broader expansion",
|
||
"rationale": "The user identified Gmail import and AI drafts as the weakest current areas and the first bar for daily use.",
|
||
"revisable": "Yes — if execution proves another blocker is more fundamental",
|
||
"made_by": "collaborative",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 6,
|
||
"id": "D006",
|
||
"when_context": "M001/S02",
|
||
"scope": "workspace-persistence",
|
||
"decision": "How the saved application answer draft should persist inside the job workspace before a dedicated field exists",
|
||
"choice": "Store the application answer draft in a replaceable notes block and make SaveApplicationDrafts overwrite notes when notes are explicitly provided",
|
||
"rationale": "The existing append-only notes behavior made the Tailored CV workspace untrustworthy because repeated saves duplicated the application answer indefinitely. A replaceable notes block preserves current schema compatibility while giving the workspace a stable saved/read-back loop for later slices.",
|
||
"revisable": "Yes",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 7,
|
||
"id": "D007",
|
||
"when_context": "M001/S01",
|
||
"scope": "gmail-continuity",
|
||
"decision": "What “good Gmail import” now means for M001",
|
||
"choice": "Treat Gmail import as full-thread continuity: the user must be able to import the whole relevant thread, and already-linked Gmail threads must refresh automatically so later inbound messages and user-sent replies appear on the job without manual re-import. This supersedes the narrower one-time-import interpretation inside D005’s Gmail-import focus.",
|
||
"rationale": "The user explicitly asked whether the app can bring the whole email thread and automatically show their reply later without re-pulling/importing again. That changes the trust bar from “find and import the right message” to “keep the linked thread current over time,” while still preserving the no-auto-send boundary from D002.",
|
||
"revisable": "Yes — if Gmail API or product constraints later require a different sync model",
|
||
"made_by": "human",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 8,
|
||
"id": "D008",
|
||
"when_context": "M001/S01 planning",
|
||
"scope": "gmail-sync",
|
||
"decision": "How linked Gmail threads stay current in S01",
|
||
"choice": "Use a job-scoped refresh flow over already-imported Gmail thread IDs, triggered from the job workspace/API, instead of building inbox-wide Gmail watch/history cursor infrastructure in M001.",
|
||
"rationale": "The codebase already persists ExternalThreadId per correspondence and lacks Gmail history/watch infrastructure. Fetching known linked threads for one job keeps scope bounded, fits the single-user workspace model, supports duplicate-safe import of new inbound and sent replies, and creates a trustworthy continuity loop without adding brittle webhook/cursor state before the milestone proves value.",
|
||
"revisable": "Yes — if real usage shows job-scoped pull refresh is too slow or misses important continuity cases.",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 9,
|
||
"id": "D009",
|
||
"when_context": "M001/S01 closure",
|
||
"scope": "gmail-matching",
|
||
"decision": "Where Gmail candidate aggregation and ranking logic should live for job-aware import",
|
||
"choice": "Keep Gmail query-hit aggregation, dedupe, matched-query traces, and ranking reasons in the backend contract instead of recreating that logic in the React workspace.",
|
||
"rationale": "The correspondence workspace needs explanatory candidate ranking plus duplicate visibility, and putting the logic in the API keeps one source of truth for scoring/import state while preventing browser-side heuristic drift.",
|
||
"revisable": "Yes",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 10,
|
||
"id": "D010",
|
||
"when_context": "M001/S03 closeout",
|
||
"scope": "followup-drafting",
|
||
"decision": "How follow-up grounding should be exposed to the workspace",
|
||
"choice": "Return explicit follow-up grounding fields (`contextSummary`, `contextSignals`, `threadSubject`, and last-correspondence metadata) from the backend DTO instead of making the React workspace infer them client-side.",
|
||
"rationale": "The slice needed draft trust, not just draft text. Putting grounding signals in the API contract gives the UI a durable explanation surface, keeps thread/package inference in one place with generation logic, and makes backend/frontend tests assert the same source of truth.",
|
||
"revisable": "Yes",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 11,
|
||
"id": "D011",
|
||
"when_context": "M001/S05 planning",
|
||
"scope": "workflow-trust",
|
||
"decision": "How S05 should represent daily-loop readiness and next-action state across overview surfaces",
|
||
"choice": "Introduce explicit workflow trust/action signals from the backend/UI contract and reuse them across the table, dashboard, reminders, and shared workspace instead of continuing to infer behavior from free-form `followUpReason` strings or raw `notes` presence in each component.",
|
||
"rationale": "S05 is an end-to-end polish slice where the remaining risk is fragmented trust, not missing subsystems. Centralizing workflow signals avoids heuristic drift between overview surfaces, respects the saved application-answer notes-block constraint, and gives the final integrated regression one source of truth for R010 while preserving the explicit manual-send boundary required by R008.",
|
||
"revisable": "Yes",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
},
|
||
{
|
||
"seq": 12,
|
||
"id": "D012",
|
||
"when_context": "M001/S05",
|
||
"scope": "workspace-observability",
|
||
"decision": "Where linked Gmail thread continuity status should be exposed in the final trust loop",
|
||
"choice": "Show linked-thread refresh state directly in the correspondence workspace, including linked thread count and last refresh outcome, instead of hiding continuity feedback inside the Gmail import modal only.",
|
||
"rationale": "The end-to-end trust loop depends on users being able to verify that already-linked Gmail threads stay current without re-importing. Surfacing continuity state in the main workspace keeps the job timeline trustworthy, supports final UAT, and avoids making thread refresh feel like a hidden one-off import behavior.",
|
||
"revisable": "Yes",
|
||
"made_by": "agent",
|
||
"superseded_by": null
|
||
}
|
||
],
|
||
"verification_evidence": []
|
||
} |