36 lines
3.8 KiB
Markdown
36 lines
3.8 KiB
Markdown
# 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`:
|
|
```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.
|