Files
jobtrackingapp/.gsd/milestones/M001/slices/S01/tasks/T01-SUMMARY.md
T
cesnimda 955cae6d4b test(S01/T01): Added a job-scoped Gmail matching contract with backend-…
- JobTrackerApi/Controllers/GmailController.cs
- JobTrackerApi/Services/GmailOAuthService.cs
- JobTrackerApi.Tests/GmailControllerTests.cs
- .gsd/milestones/M001/slices/S01/S01-PLAN.md
- .gsd/KNOWLEDGE.md
2026-03-24 12:07:25 +01:00

5.6 KiB
Raw Blame History

id, parent, milestone, provides, key_files, key_decisions, patterns_established, observability_surfaces, duration, verification_result, completed_at, blocker_discovered
id parent milestone provides key_files key_decisions patterns_established observability_surfaces duration verification_result completed_at blocker_discovered
T01 S01 M001
Job-scoped Gmail candidate ranking metadata with weighted reasons, matched-query traces, and duplicate visibility for one owned job.
JobTrackerApi/Controllers/GmailController.cs
JobTrackerApi/Services/GmailOAuthService.cs
JobTrackerApi.Tests/GmailControllerTests.cs
.gsd/milestones/M001/slices/S01/S01-PLAN.md
.gsd/KNOWLEDGE.md
Moved Gmail query-hit aggregation into the backend service so the UI can consume ranked candidates without recreating dedupe or scoring heuristics.
Job-aware Gmail candidates now expose weighted match reasons, matched query strings, per-thread imported counts, and explicit empty-state counts.
api/gmail/job-candidates response metadata
api/gmail/status
JobTrackerApi.Tests/GmailControllerTests.cs
.gsd/KNOWLEDGE.md
~1h partial 2026-03-24T12:00:00+01:00 false

T01: Add a job-aware Gmail matching contract and backend ranking tests

Added a job-scoped Gmail matching contract with backend-owned query aggregation, weighted ranking reasons, duplicate visibility, and focused controller test coverage.

What Happened

I extended api/gmail/job-candidates so it now loads an owned job with company and correspondence context, explicitly constrains lookup to the authenticated owner, and returns richer ranking metadata for UI consumption instead of leaving ranking logic in the browser.

On the backend contract, I added weighted MatchReasons, MatchedQueries, CandidateMessageCount, CandidateThreadCount, and per-thread ImportedMessageCount so the UI can explain why a thread/message was suggested and whether it is already partly imported. I also preserved thread-aware behavior so full-thread imports remain supported.

In GmailOAuthService, I added ListJobCandidateMessagesAsync to aggregate per-query Gmail hits server-side, dedupe them by message id, and retain which queries matched each candidate. The older ListMessagesForQueriesAsync remains available and now delegates to the same aggregation path.

In JobTrackerApi.Tests/GmailControllerTests.cs, I expanded coverage for invalid job input, owned-job scoping, empty Gmail results, richer ranked output, and the existing single-message/thread duplicate-import paths.

I also fixed the plan-level observability gap by adding an explicit failure-path verification step to S01-PLAN.md, and I recorded a project-specific verification gotcha in .gsd/KNOWLEDGE.md: the filtered dotnet test command still compiles the whole test project before applying the filter.

Verification

I built the API project to confirm the controller/service changes compile cleanly.

I ran the slices backend verification command. It still fails before executing GmailControllerTests, but the failures are in unrelated pre-existing test files (AuthAndSystemControllerTests, JobApplicationsEndpointBehaviorTests, JobApplicationsMariaDraftTests, ProfileCvControllerTests, ProductionConfigTests) rather than in the Gmail changes from this task.

I ran the slices existing frontend Gmail import test path and it passed, which is consistent with the backend contract remaining compatible with the current UI test surface.

Verification Evidence

# Command Exit Code Verdict Duration
1 dotnet build JobTrackerApi/JobTrackerApi.csproj 0 pass 1.41s
2 dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests 1 fail 1.71s
3 CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/correspondence-gmail-import.test.tsx 0 pass 3.07s

Diagnostics

Inspect api/gmail/job-candidates to see:

  • CandidateMessageCount and CandidateThreadCount for empty/noisy result diagnosis
  • per-thread MatchedQueries, ImportedMessageCount, HasImportedMessages, Score, and Confidence
  • per-message MatchedQueries, AlreadyImported, and weighted MatchReasons

Inspect api/gmail/status for Gmail connection state, and read JobTrackerApi.Tests/GmailControllerTests.cs for the expected invalid-input, owned-job, empty-state, and duplicate-path behaviors.

Deviations

None beyond a local path correction: the data/model files live under Data/ and Models/ in this worktree rather than under JobTrackerApi/Data and JobTrackerApi/Models.

Known Issues

  • The slice backend verification command is still blocked by unrelated compile failures elsewhere in JobTrackerApi.Tests; those failures are outside the Gmail files changed in this task.
  • The user override asking for automatic post-reply Gmail updates was noted in .gsd/OVERRIDES.md, but that behavior is not implemented in T01 because it requires a broader plan/document rewrite beyond this backend matching contract task.

Files Created/Modified

  • JobTrackerApi/Controllers/GmailController.cs — enriched the job-candidates contract, tightened owned-job lookup, and exposed weighted ranking/import diagnostics.
  • JobTrackerApi/Services/GmailOAuthService.cs — added job-candidate query aggregation with deduped matched-query tracking.
  • JobTrackerApi.Tests/GmailControllerTests.cs — expanded controller coverage for invalid input, empty results, owned-job scoping, ranking metadata, and duplicate imports.
  • .gsd/milestones/M001/slices/S01/S01-PLAN.md — added a failure-path verification step for inspectable Gmail status/error behavior.
  • .gsd/KNOWLEDGE.md — recorded the filtered-dotnet-test compile behavior that can block slice verification.