[1.13.0] — 2026-05-13
Big slice. Closes all 4 deferred items from the post-v1.12.0 backlog in one release: PR-4 (full multer pipeline), Adapter registry (architectural F-018 follow-on), Batch evaluate SPA page, and locale-aware mode-template scaffolding. Plus a mid-session dark-theme table fix.
✨ Features
feat(cv): multer-based multipart upload (PR-4 full)—/api/cv/importnow accepts BOTH the original octet-stream contract (Content-Type: application/octet-stream+X-Filename) ANDmultipart/form-dataproperly parsed via multer. The v1.10.2 415-reject was a stopgap; v1.13.0 is the real fix. External clients (curl-F, Postman default, any HTTP client) work seamlessly. Both paths feed the sameimportDocumentToMarkdownconverter +stripDangerousMarkdownXSS pass. New dep:multer ^2.1.1.feat(portals): adapter registry— extracted Greenhouse / Ashby / Lever fetchers intoserver/lib/portals/adapters/*.mjswith a uniform contract (id,label,matches,buildEndpoint,fetch). Newserver/lib/portals/registry.mjs::resolveAdapter()is the single dispatch surface.en-scanner.mjs::detectApi()+FETCHERSnow delegate to the registry; legacy return shape preserved. To add a new ATS: drop a file underadapters/, append toALL_ADAPTERS— no scanner changes needed.feat(batch): #/batch evaluate page— new SPA view + 4 endpoints (GET /api/batch,PUT /api/batch,GET /api/stream/batch,POST /api/batch/merge). TSV editor forbatch/batch-input.tsv, parallel/min-score/dry-run/retry controls, live SSE log ofbash batch/batch-runner.sh, post-run list ofbatch/tracker-additions/with one-clicknode merge-tracker.mjs. Sidebar link under Decision group. 21 new i18n keys × 8 locales.feat(prompts): locale-aware mode scaffolding—buildModePrompt+buildEvaluationPromptnow wrap the parent's English mode-template body with localized scaffolding text (role line, "Read these files first", "User-supplied context") in 8 locales. The parent'smodes/<slug>.mdbody stays English (read-only per CLAUDE.md hard rule #1); the career-ops-ui scaffolding around it is translated.
🎨 UX fixes
fix(theme): dark-mode table hover + tab-btn— hardcoded#fafafa/#fff/#f7f7f7replaced withvar(--beach)/var(--paper)/var(--slate)tokens so the dark palette swap actually reaches table rows and tab buttons. Adds.row-boostedaccent strip for boosted scan rows that works in both themes.
🧪 Tests
- New
tests/adapter-registry.test.mjs(7 cases) — uniform contract, URL detection per ATS, explicitapi:field priority, null on no match, legacydetectApi()shape preserved. - New
tests/batch-endpoints.test.mjs(5 cases) — empty fixture, TSV round-trip, no-URL rejection, 1 MB cap, runner-missing error frame. - New
tests/locale-scaffold.test.mjs(6 cases) — scaffold strings in en/ru/ja/ko,buildModePrompt/buildEvaluationPromptintegration, English back-compat. tests/cv-upload-multipart-reject.test.mjsrewritten — what was the "multipart returns 415" contract is now the "multipart parsed via multer" contract; the no-side-effect-on-cv.md invariant is preserved.- Total: 379 / 379 unit tests (was 360; +19 net). 0 failures.
- Coverage: 95.46 % line / 84.06 % branch.
- 20/20 smoke E2E · 23/23 comprehensive E2E · 28/28 Playwright.
Out of scope (deferred follow-up work)
| Item | Notes |
|---|---|
| 14 new portal adapters (Workable / SmartRecruiters / Workday / GitLab / HashiCorp / Cloudflare / Datadog / Stripe / Notion / Linear / Posthog / Hugging Face / Replicate / Modal Labs / Fly.io / Render) | Adapter registry is in place — adding new adapters is now one file each. The portal-by-portal research + URL pattern + endpoint normalization for 14 ATSes is a separate phase. |
Translating parent's modes/<slug>.md bodies
| Parent files are read-only per CLAUDE.md hard rule #1. v1.13.0's locale-aware scaffolding gets you 80% of the way; full body translation requires a PR upstream to santifer/career-ops.
|
Docs
docs/reviews/REVIEW-2026-05-13-v1.13.0.md— session context + adapter registry contract + batch flow.- All 8 READMEs: badge bumps (tests 360 → 379, release v1.12.0 → v1.13.0).
- All 8 CHANGELOGs receive this entry.