mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-08 07:57:40 +00:00
fix(upskill,notion-sync): join tracker rows to ranked entries on title, the field entries carry (#614)
Both specs said to match "on company + role" with "casefold + strip on both fields", but a seen_jobs.json entry has title and no role key (the job-scraper schema), so read literally the lookup never matched: /upskill then weighted the same job twice, once as a tracker row and once as a ranked entry - the double-count its dedupe step exists to prevent - and /notion-sync split one job into two rows with different Keys. tools/rank_state.py already does the cross-name join (tracker role against entry title); both specs now say so. Two derived tests read the entry schema and require the join wording to name title for the entry and role for the tracker; they fail on master.
This commit is contained in:
1 parent
709339758a
commit
2697fa46fb
5 files changed
+46
-3
No files matched your search
@@ -40,7 +40,7 @@ Validate the cheap, local precondition before creating anything external. A run
|
||||
|
||||
1. Read `job_scraper/seen_jobs.json` and `job_search_tracker.csv` (either may be missing).
|
||||
2. Select `seen_jobs.json` entries with status `ranked` whose `rank_score` meets the threshold from Step 0. `--all` lifts the threshold entirely.
|
||||
3. Every tracker row joins the sync set (an applied-to job always syncs, ranked or not), matched to `seen_jobs.json` entries case-insensitively on company + role where possible. Tracker rows with no `seen_jobs.json` entry sync too - build their Key as `<company>_<role>` lowercased with underscores.
|
||||
3. Every tracker row joins the sync set (an applied-to job always syncs, ranked or not), matched to `seen_jobs.json` entries case-insensitively on company + title where possible (the tracker's `role` column against the entry's `title` field — entries carry `title`, not `role`). Tracker rows with no `seen_jobs.json` entry sync too - build their Key as `<company>_<role>` lowercased with underscores.
|
||||
4. **Status precedence:** the tracker wins. A job that is `ranked` in `seen_jobs.json` but `interview` in the tracker syncs as `interview`. Jobs only in `seen_jobs.json` keep their stored status. **Deadline precedence: the tracker wins too** - the tracker's `deadline` (written by `/apply` from the posting the application was actually built on) overrides the `seen_jobs.json` value; jobs only in `seen_jobs.json` keep the scraper's stored deadline. Omit the property when neither states one, and **never reconcile the two by picking the earlier or later date** - both were read from the posting at different times, and the safe-looking `min()` substitutes a date the user never applied against.
|
||||
5. **If the sync set is empty** (no ranked entries meet the threshold and there are no tracker rows), say "Nothing to sync - run `/scrape` and `/rank` first" (or, when jobs exist but all score below the threshold, say so and suggest `--min-score`/`--all`) and **stop**.
|
||||
6. State the counts before touching the destination: how many rows will be created or checked, and the threshold in effect.
|
||||
|
||||
Reference in new issue
Block a user