[1.256.0] — 2026-10-25
Tracker data quality: the role is never filed as the company, a job board is never filed as the employer, unscored rows stop surfacing first — and a one-shot endpoint backfills missing scores from the reports themselves.
Added
- Score backfill (CAR-129):
POST /api/tracker/backfill-scoresfills the Score cell of rows whose linked report carries a parseable score (181 evaluated rows had a report but no score). Scored rows, explicit sentinels (N/A), report-less rows and scoreless reports are never touched; only the Score cell is rewritten, under the file lock; the score shape is validated at the write site and normalized to the tracker'sX.X/5convention; the run is idempotent and returns{ok, updated, missingReport, reportScoreless}.
Fixed
- The role is never the company (CAR-128):
guessCompanyRoletreated the LEFT side of a dash header line as the company, but boards write both orders — «Senior Frontend Engineer - Grafana Labs» filed the role AS the company (13 rows: Grafana, CircleCI…). A word-bounded role-keyword heuristic now picks the role side, and an employment type never becomes the employer («Senior Engineer - Remote (EU)» files nothing rather than «Remote (EU)»). - A job board is never the employer (CAR-127): the domain-slug fallback filed hh.ru rows as «hh» (120 rows).
hh/habrslugs join the not-an-employer list; the mid-sentence employer inference («в компании X», «X ищет») now runs for job-board hosts (hh.ru/kz/uz/by, habr.com) too — where the page text names the real employer. Root cause found on the way: the ASCII\b/\win those inference patterns never matched Cyrillic at all — silently dead since v1.248.4; Unicode lookbehinds and\p{L}classes replace them. - Unscored rows sort last (CAR-129): the tracker's score sort used a
-1sentinel, so with the default ascending sort every unscored row surfaced before every scored one. Nulls now sort last in both directions (the score FILTER keeps its-1— "unscored fails a ≥4 filter" is correct semantics there).
Notes
- Historical rows are NOT migrated by this release: the parser fixes apply to new evaluations; scores are recoverable via the backfill endpoint, while the 120 «hh» employer cells need re-evaluation, not a rewrite.
- An opus-5-5 review round is folded in: the unanchored «X ищет» pattern was dropped before shipping (any capitalised run before the verb would have been filed as an employer — the no-fabrication invariant), sentence-initial «В…» anchors added, and the backfill writer re-checks the target cell (duplicate
#rows exist after manual edits), keeps a hand-malformed short row's column count, and stops at the first non-table line. The dot inside a dotted name («Сбер. IT») is indistinguishable from a sentence dot for the «в компании» anchor — the conservative prefix («Сбер») is filed; the verb-anchored pattern catches the full form. - Deliberately not done: no comparator extraction from
tracker.jsinto a unit-testable lib (the source-static gate stays; noted in CAR-129 as follow-up), no commute-column nulls-last change (pre-existingInfinity-on-desc quirk), no data migration for the «hh» rows. - Tests 5705 (+10: 5 identity in
auto-pipeline-jd-gate, 2 CAR-128, the CAR-129 sort gate, 4 backfill incl. the hostile-path pin — minus the replaced v1.248.x cases). No scanner sources touched (registry 121 = 116 EN + 5 RU · 116 adapters); no i18n keys.