feat(S05/T02): Added an end-to-end trust-loop regression, surfaced save…

- 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
- .gsd/milestones/M001/slices/S05/S05-UAT.md
This commit is contained in:
2026-03-24 14:36:46 +01:00
parent 9f631ca320
commit a0d1c1c05b
7 changed files with 436 additions and 2 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ The work is grouped into two tasks because the slice has two different risks. Fi
- Do: add explicit workflow trust/action fields or normalized routing metadata at the controller/DTO layer, introduce a shared UI helper that consumes those fields instead of parsing free-form strings or raw `notes`, and update table/dashboard/reminders to route from the same source of truth without breaking the existing shared `/jobs?open=...&tab=...` workspace entry pattern.
- 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`
- Done when: the overview surfaces and readiness logic describe the same next action for the same job without depending on ad-hoc string matching or treating all `notes` content as generic package readiness.
- [ ] **T02: Add integrated trust-loop proof and workspace polish** `est:5h`
- [x] **T02: Add integrated trust-loop proof and workspace polish** `est:5h`
- Why: the milestone still needs one trustworthy proof path that composes the existing package, Gmail, and follow-up slices and exposes any remaining trust gaps in the real workspace.
- 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`
- Do: add a focused integrated UI regression that starts from an overview entry surface and walks through saved package reuse, linked-thread continuity, and grounded follow-up drafting; patch only the workspace/continuity UI needed to make that path trustworthy and explicit; and capture a live-safe UAT script that preserves the manual-send boundary.
@@ -0,0 +1,90 @@
# S05 Live-Safe UAT: Trust Loop Verification
## Goal
Verify the end-to-end trust loop on one real job without accidentally sending recruiter email.
## Safety Guardrails
1. **Do not press `Send and log email`** unless the environment is explicitly configured to a safe sink, stub mailbox, or other non-production outbound target.
2. If you are not certain the outbound email path is safe, stop after reviewing the generated follow-up draft.
3. Do not paste private recruiter or correspondence bodies into screenshots, tickets, or logs.
4. Prefer a job that already has:
- saved package material on the job,
- at least one linked Gmail thread,
- a follow-up reason/readiness signal.
## Preconditions
- The API and UI are running against the intended environment.
- Gmail integration is authenticated for the current user.
- The selected job has an identifiable company, job title, and recruiter mailbox/thread history.
- If you plan to verify the send step, outbound email must point at a safe sink/stub. Otherwise stop before sending.
## Shared Expected Trust Signals
The same job should present one coherent next action across all entry points:
- `/jobs`
- `/dashboard`
- `/reminders`
The workspace should make these states clear:
- saved package material can be reused,
- linked Gmail refresh checks already-linked threads instead of requiring full re-import,
- follow-up draft generation is grounded in saved package + correspondence context,
- email sending remains manual.
## Flow A — Start from `/jobs`
1. Open `/jobs`.
2. Find a job with a trust/workflow signal chip or next-action button.
3. Open the job via the primary next-action control.
4. Confirm the workspace opens on the expected tab for that action.
5. In **Tailored CV**:
- verify the saved tailored CV, cover letter, application answer, and recruiter message are present if the job previously had them,
- confirm the workspace explicitly says the saved package material feeds follow-up drafting.
6. In **Correspondence**:
- confirm the linked-thread continuity panel is visible,
- confirm Gmail connection state is shown,
- confirm linked thread count is shown when applicable,
- trigger **Refresh linked threads** if manual confirmation is needed,
- verify new linked correspondence appears without importing the full thread again.
7. In **Follow up**:
- confirm the draft context references saved package material and thread context,
- confirm the manual-send boundary copy is visible,
- review the generated draft but **stop before `Send and log email`** unless the environment is explicitly safe.
## Flow B — Start from `/dashboard`
1. Open `/dashboard`.
2. Find the same job in an attention/reminder card.
3. Open it from the dashboard action.
4. Confirm it lands in the same job workspace and the same trust state is visible:
- package material is still saved,
- correspondence continuity is preserved,
- follow-up context remains grounded.
## Flow C — Start from `/reminders`
1. Open `/reminders`.
2. Find the same job in the appropriate reminder grouping.
3. Open it from the reminder action.
4. Confirm it lands in the same workspace for the same job and preserves the same action semantics.
## Pass Criteria
- The same job can be opened from `/jobs`, `/dashboard`, and `/reminders`.
- The saved application package is visible and clearly reusable for follow-up drafting.
- Linked Gmail refresh shows continuity on already-linked threads without requiring a whole-thread re-import workflow.
- The follow-up draft is grounded in saved package and correspondence context.
- No recruiter email is sent unless the human explicitly chooses `Send and log email` in a safe environment.
## Failure Clues
- Entry points route to different tabs or imply different next actions for the same job.
- Saved package material is missing or no longer called out as reusable context.
- Linked-thread refresh state is invisible or requires re-importing a thread that is already linked.
- Follow-up drafting triggers outbound send behavior or makes send/regenerate coupling unclear.
- Workspace state differs depending on whether the job was opened from jobs, dashboard, or reminders.
@@ -0,0 +1,77 @@
---
id: T02
parent: S05
milestone: M001
provides:
- Integrated trust-loop regression covering overview entry, saved package reuse, linked Gmail continuity, and grounded follow-up drafting
key_files:
- 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
- .gsd/milestones/M001/slices/S05/S05-UAT.md
key_decisions:
- Exposed linked-thread refresh status directly in the correspondence workspace instead of hiding continuity feedback inside the Gmail import modal.
patterns_established:
- Integrated workflow proof should open the real job workspace from an overview action, then verify package reuse, correspondence continuity, and follow-up draft/manual-send separation in one test.
observability_surfaces:
- 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
- .gsd/milestones/M001/slices/S05/S05-UAT.md
- GET /api/jobapplications/{id}/followup-draft
- GET /api/correspondence/{jobId}
- POST /api/gmail/refresh-linked-threads
duration: 33m
verification_result: passed
completed_at: 2026-03-24T14:35:40+01:00
blocker_discovered: false
---
# T02: Add integrated trust-loop proof and workspace polish
**Added an end-to-end trust-loop regression, surfaced saved-package and Gmail continuity trust state in the workspace, and documented a live-safe UAT runbook.**
## What Happened
I verified the existing S01-S04 tests and workspace code first, then added a new focused React regression at `job-tracker-ui/src/end-to-end-trust-loop.test.tsx` that starts from the real `/jobs` overview action path and proves the composed loop in one place: open the workspace from the overview, confirm saved package material is already present, confirm linked Gmail thread refresh brings in new correspondence without re-importing the thread, and confirm the grounded follow-up draft remains available without calling `send-followup`.
To make that integrated path trustworthy in the actual UI, I limited code changes to the two planned components. In `JobDetailsDialog.tsx`, I tightened the package-reuse copy and added an explicit manual-send boundary panel in the follow-up workspace so draft generation/regeneration cannot be mistaken for sending. In `Correspondence.tsx`, I added a linked-thread continuity panel to the main workspace so Gmail connection state, linked-thread count, and last refresh outcome are visible without opening the import modal.
I also wrote `.gsd/milestones/M001/slices/S05/S05-UAT.md` as the live-safe runbook for the final human loop. It tells a human how to verify `/jobs`, `/dashboard`, and `/reminders` against real services while stopping before `Send and log email` unless outbound mail is explicitly pointed at a safe sink/stub.
## Verification
I ran the full slice command suite: the backend workflow-signal tests, the focused workflow-signal React suite, the new integrated trust-loop regression, the existing Gmail/package/follow-up/daily-loop bundle, and the production build. All command-based verification passed.
I also attempted a real browser sanity pass by starting the local UI and navigating to `http://localhost:3000/jobs`. The browser reached the app shell, but the live verification could not proceed because an already-running process on port `5202` responded without the expected CORS headers, so the UI could not load API data. I did not treat that as a slice blocker because it is an environment/runtime collision outside the T02 code changes, and the live-safe UAT runbook is now ready for a correctly configured environment.
## Verification Evidence
| # | Command | Exit Code | Verdict | Duration |
|---|---------|-----------|---------|----------|
| 1 | `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter JobApplicationsWorkflowSignalsTests` | 0 | ✅ pass | 4.79s |
| 2 | `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/workflow-trust-signals.test.tsx` | 0 | ✅ pass | 3.85s |
| 3 | `CI=true npm --prefix job-tracker-ui test -- --watch=false --runTestsByPath src/end-to-end-trust-loop.test.tsx` | 0 | ✅ pass | 3.58s |
| 4 | `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` | 0 | ✅ pass | 6.54s |
| 5 | `CI=true npm --prefix job-tracker-ui run build` | 0 | ✅ pass | 15.55s |
## Diagnostics
Use `job-tracker-ui/src/end-to-end-trust-loop.test.tsx` as the single integrated proof for the slice. Inspect `job-tracker-ui/src/components/JobDetailsDialog.tsx` for the saved-package reuse and manual-send boundary copy, and inspect `job-tracker-ui/src/components/Correspondence.tsx` for linked-thread continuity state. For live verification, follow `.gsd/milestones/M001/slices/S05/S05-UAT.md`. If the real browser flow fails, inspect `GET /api/jobapplications/{id}/followup-draft`, `GET /api/correspondence/{jobId}`, and `POST /api/gmail/refresh-linked-threads` together with browser network/CORS diagnostics.
## Deviations
I did not need to update `job-tracker-ui/src/daily-control-loop.test.tsx` because the shared entry semantics from T01 still held once the integrated regression was added.
## Known Issues
- A live browser sanity attempt against `http://localhost:3000/jobs` was blocked by a pre-existing process bound to port `5202` that did not return the expected CORS headers for `http://localhost:3000`, so the app shell loaded but API-backed job data did not. The code changes in this task were still verified through the full automated command suite.
- React Router future-flag warnings still appear during test runs, but they are warnings only and did not affect pass/fail outcomes.
## Files Created/Modified
- `job-tracker-ui/src/end-to-end-trust-loop.test.tsx` — added the integrated overview → workspace → package reuse → Gmail continuity → follow-up/manual-send regression.
- `job-tracker-ui/src/components/JobDetailsDialog.tsx` — clarified saved-package reuse and added explicit manual-send boundary copy in the follow-up workspace.
- `job-tracker-ui/src/components/Correspondence.tsx` — surfaced linked-thread continuity and last-refresh status directly in the main correspondence workspace.
- `.gsd/milestones/M001/slices/S05/S05-UAT.md` — documented the live-safe final human verification flow and send-safety guardrails.
- `.gsd/milestones/M001/slices/S05/S05-PLAN.md` — marked T02 complete.