jobhunt-platform/docs/worker-tasks/v11-wave-b.md
hermes 59ea645125
Some checks failed
CI / api-tests (push) Failing after 30s
CI / package-tests (push) Failing after 38s
CI / web-tests (push) Failing after 33s
v1.1 wave B dispatch cards (dedupe+tailor+deadline api, web v1.1 UI)
2026-07-30 20:47:07 +00:00

3.8 KiB

v1.1 worker dispatch — wave B

Global v1 rules binding (see v1-tasks.md header). Wave A is merged into master: packages/matching exists (cluster(), keywords coverage()), llm-gateway has mocks for cv_tailor (STRONG) + deadline_extract (CHEAP) + email_classify, api has email_suggestion + notification_log tables and /suggestions + /notifications/log endpoints (125 api tests green).

WB1: apps/api — dedupe + tailor + deadline integration

Paths: apps/api/** ONLY (you own apps/api this wave).

Migration 004_dedupe_deadline.sql:

ALTER TABLE job_posting ADD COLUMN IF NOT EXISTS cluster_id text;
ALTER TABLE job_posting ADD COLUMN IF NOT EXISTS apply_by date;

Deliverables:

  • Cluster assignment: on job_posting creation (manual POST /postings AND /postings/fetch), run packages/matching cluster() over the new posting + all existing postings (small N, fine at v1 scale); persist cluster_id; new clusters only when no match (cluster() output may re-group - reconcile: prefer stability, assign new posting into existing cluster_id when rule matches, else fresh id).
  • Read: GET /postings gains cluster_id; new GET /clusters -> [{cluster_id, postings: [{id, title, company, source, url, score}]}] sorted by best score desc; UI uses this for "same role via 3 agencies".
  • Tailor CV: POST /applications/{id}/tailor-cv -> gateway task cv_tailor (STRONG) with prompt = profile + sections + posting description; validate output schema {sections, change_log[]}; hallucination guard check: every tailored bullet must map to a source bullet id from input (reject + 502 on unmapped bullet); store artifact kind='cv' origin='ai_drafted' + render PDF via packages/artifacts (bytes -> hash -> storage); return {artifact_id, change_log, keyword_coverage: coverage(cv_text, posting.description)}.
  • Deadline: scoring endpoints (single + batch) additionally run deadline_extract (CHEAP) and persist apply_by when non-null; /today adds deadlines: [{application_id, title, company, apply_by}] for apply_by within next 7 days.
  • Dockerfile.test: add -e /app/packages/matching install.
  • Tests (+ >= 20): cluster assignment on create, cluster stability across re-imports, clusters endpoint shape, tailor-cv happy path + hallucination rejection (fabricate mock returning bullet without source id -> 502), keyword coverage numbers vs fixture, deadline persisted + /today deadlines filter window.
  • docker compose run --rm api-test all green (125 + yours). Branch feat/WB1-dedupe-tailor, commit incrementally, push.

WB2: apps/web — v1.1 UI

Paths: apps/web/** + docs/user-guide.md (edit allowed, append section) ONLY.

Backend per docs/api-contract-v2.md + wave A/B adds: /suggestions (accept/dismiss), /notifications/log, /clusters, tailor-cv, /today.deadlines. Mock these in tests like before.

  • Today view: new "Deadlines this week" strip (cards with company/title/date, red when <=2 days) from GET /today.deadlines; "Inbox insights" strip listing pending email_suggestion rows (from/subject/snippet/classification chip) with Accept/Dismiss buttons -> POST endpoints, then refresh; notifications mini-log (last 5) optional.
  • Research/Postings: group rows by cluster; cluster rows show "also via N more" expandable alternates list (GET /clusters).
  • Application detail: "Tailor CV for this job" button -> POST tailor-cv -> panel showing change_log bullets + keyword coverage bar + link to download artifact; variant appears in artifacts list.
  • CostDisplay: add totals by provider (group /telemetry/tasks client-side).
  • Vitest: +4 tests (deadlines strip render, suggestions accept flow, cluster alternates render, tailor panel render from fixture). Keep all existing green. npm run build + npm test green.
  • docs/user-guide.md: append "v1.1: email radar, dedupe, tailor CV" short section (plain language, no em dashes).
  • Branch feat/WB2-web-v11, commit incrementally, push.