Changelog

Every release, in plain language. career-ops ships several times a week; this page reads straight from GitHub Releases and updates itself. Your data is never touched by an update — see the Data Contract.

v1.28.0

Latest

New

  • application-answersParse a rendered section back into a snapshot
  • batchNative Node.js batch evaluator for Gemini
  • company-historyEmit no-response-friction signal per RFC #1506 schema v1
  • cvMake Work Experience an optional section
  • discover-atsProbe the long-tail ATS vendors, not just the big three
  • doctorEmit the Gemini Node 20+ verdict instead of leaving it in prose
  • followupsExport withFollowupsLock so other writers can share the lock
  • ofertaAI-screening disclosure signal — Block G Signal 15
  • portalsAdd Wellfound search queries to the example template
  • providersAdd yourator job board provider
  • reportsAdd reports_to to the Machine Summary schema
  • scan-ats-fullOptional title_filter_full override for the full-board sweep
  • titlesLet the mode retire a keyword, not only add one

Fixed

  • add-entryExact-match dedup keys so a prefix cannot false-positive
  • archive-postingReject mistyped flags via the shared helper
  • batch-runnerCurl pre-fetch JD file to avoid empty $jd_file fallback
  • batch-runnerEmit the JD word count color-independently
  • classify-tierValidate CLI flags and add a usage block
  • considerPerform GET /jobs CSRF handshake before the POST
  • contactsAdd -h/--help and reject unrecognized flags
  • cover-letterPreserve --out subdirectories inside the output root
  • cvAn empty Skills section no longer deletes the sections after it
  • funnel-velocityValidate CLI flags via the shared helper
  • intakeTreat a nonzero version probe as present, not missing
  • livenessRead same-origin iframes so embedded postings aren't false negatives
  • locksThe other two copies of the protocol had the same Windows bug
  • merge-trackerDon't let an unscoreable (N/A) re-eval overwrite a real score
  • merge-trackerWrite rows at the header's actual width on customized trackers
  • pipeline-lockAn unreadable owner stamp is not an ownerless lock
  • pipeline-lockTime out a wedged holder, not an unlucky waiter
  • pipelineSerialize browser-backed extraction so workers never share a session
  • portalsBlock German student and support postings in the example title filter
  • portalsRefresh example board URLs after ATS migrations
  • providersRaise inter-page pacing to 250 ms on the eight providers still at 150
  • providersSenjob was the fifth private entity decoder, and the weakest — it emitted C0 controls
  • scanAdd block_hard tier so always_allow cannot discard an explicit block
  • set-statusRejects today's date east of UTC, logs tomorrow's west of it
  • statsValidate CLI flags via the shared helper
  • test-allTolerate Windows EPERM on fixture cleanup so a green run stays green
  • trackerTreat Windows rename contention as contention, not death
  • trust-validatorA company with an accent in its name is flagged for being on its own domain
  • updaterDetect tree drift and prune retired system files (#2630, #2532)
  • updaterParse git status paths from untrimmed output
  • upskillValidate CLI flags via the shared helper
  • verify-cv-factsCatch fabricated headcounts outside software
  • verify-portals--add probes slugs that cannot exist for an accented company name
  • webBlock_hard survives the Explore round-trip — type, URL params, seed and serializer
  • webPersist the only installed CLI so jobs can start
  • webResolve 27 unmapped states.yml aliases and fix the Turkish status fold
  • webResolve company logos by name, not one guessed domain
  • webSafe Codex AI-search exec with mtime-keyed capability cache
  • webStop first-run from claiming no setup
  • webTake the core followups lock so web writes cannot race the seeder
  • webToday primary action opens the report
  • workspaceKeep artifacts and PDF metadata in the tracker's workspace

v1.27.0

New

  • cliAdd --help / -h usage block to stats.mjs
  • cliShared flag-validation helper, migrate 3 fixed scripts, fix scan.mjs, closes #2775
  • dashboardAdd a POSTED column showing requisition age
  • dashboardAdd Stats analytics view with score quality & seniority mix charts
  • intakeRead documents/ locally to propose source-annotated profile additions
  • invite-matchDistinguish AI-interviewer platforms from human calls, closes #2673
  • negotiationROI-based salary-negotiation talking points from verified achievements
  • pdfBatch render path reusing one Chromium across N CVs
  • providersEightfold AI talent-acquisition boards
  • providersExtend getro with auto-resolve, salary, retry and remote-detect, closes #2602
  • providersSenjob — the scanner's first African source, Senegal
  • rankOpt-in LLM relevance re-ranker for pipeline.md
  • scanAND-groups in title_filter.positive
  • scanRecord failed runs in scan-runs.tsv so trends exclude survivorship bias
  • skill-extractRecognize certifications, not just engineering tools
  • templatesFive named CV templates + a contract test for template variants
  • tracker-sync-checkFlag applications.md rows that active-interviews.md has already moved past
  • updateDeclare fork-local paths outside the system layer
  • updateRestore locally deleted system files instead of preserving the deletion
  • webGive the Apply page a way back and a way to record that you applied

Fixed

  • add-entryKey non-Latin headings and dedup keys faithfully
  • add-entryReject mistyped flags instead of reading them as data
  • agent-inboxGive concurrent add() a burst-sized lock timeout, closes #2824
  • agent-inboxSerialize concurrent adds through the shared lock
  • agent-inboxStop dropping requests queued during an add
  • archiveKey JD captures to report numbers so they resolve after capture day
  • assessment-logReject unknown flags
  • batch-tailor--min-score 4.5 was silently ignored, and the worker's pdf mode path was cwd-relative
  • batchRetry state updates and lock reservations to prevent worker silent drops
  • build-cv-htmlRender numeric year/date scalars instead of dropping them
  • build-cv-latexNumeric year/date scalars are still dropped — #2641 fixed only the HTML mirror
  • check-table-freshnessValidate CLI flags and add a usage block, closes #2855
  • ciOnly greet a first-time contributor when it is actually their first
  • ciSkip the upgrade leg when nothing managed changed, instead of failing
  • classify-tierAn incidental senior word outranked an explicit intern marker
  • cliA one-letter typo returned a false all-clear at exit 0 in 4 reporting CLIs
  • company-historyRecord response dates via --on, not --note free text
  • contactoLinkedIn connection-request limit is 200 on free tier, not 300
  • csodReplay bootstrap session cookies and repair fetchResponse()
  • cv-factsTreat a k/M/B magnitude suffix as part of the number
  • cvKorean and Traditional Chinese CVs had no font rule
  • dedup-trackerReject unrecognized flags instead of silently live-running
  • depsMake js-yaml imports work on both 4.x and 5.x
  • depsPatch both HIGH advisories in web (js-yaml 4.3.1, nanoid 3.3.18)
  • depsRaise the js-yaml floor to ^4.3.1 and guard it
  • doctorDetect Playwright MCP servers provided by Claude Code plugins
  • doctorValidate CLI flags and add a usage block, closes #2856
  • evalMerge openrouter tracker TSVs and send Ollama options to the native /api/chat
  • findPrint the one USAGE constant on the empty-query path too
  • findReject mistyped flags instead of searching for them
  • followup-cadenceParse annotated pins, and add a retire directive
  • followup-seedResolve "today" in local time, not UTC
  • followupIgnore an apply date cited about another row, closes #2607
  • invite-matchValidate CLI flags and add usage
  • jd-similarityAdd --help and reject unknown flags instead of reading them as paths, closes #2772
  • jd-similarityThe seniority gate fired on JD boilerplate
  • jd-skill-gapRecognize all six markdown heading levels
  • jd-skill-gapRecognize sentence-form requirement headings
  • jobviteMigrate to the public XML feed after the JSON API retirement
  • keysStop the dotted-I fix from collapsing Polish, Lithuanian and Maltese
  • keysStop the Turkish dotted capital from splitting one employer in two
  • livenessClassify a rate-limited posting as uncertain, not expired
  • livenessTreat an api.lever.co 404 as inconclusive, not proof of removal
  • locksTreat Windows rm/stat contention as contention, not death
  • match-starScore a non-English story bank against a question in its own language
  • merge-trackerDeterministic dedup on the posting URL
  • merge-trackerMatch inline URL headers so URL dedup activates for doc-style rows
  • merge-trackerRe-eval no longer inherits the superseded report's checkmark
  • ollamaInclude profile context in evaluations
  • oraclecloudAccept Oracle's numbered tenant apexes (oraclecloud1-99.com)
  • patternsRate denominators counted rows that could never contribute
  • pipeline-lockA non-EEXIST mkdir refusal is contention, not a fatal error, closes #2777
  • pipeline-lockJitter the retry so a starved writer costs a retry, not an item
  • plugin-auditValidate CLI arguments and add a usage block, closes #2771
  • process-qualityThree undisclosed employers were reported as disclosed
  • providersDecode HTML entities in titles before matching so encoded ampersands stop dropping jobs
  • providersFill in the docs and vendor-detection gaps
  • providersHarden workable with retry, headers, and serialization
  • providersIsRetryableError no longer misclassifies a refused redirect
  • providersMake themuse resilient to per-page fetch failures
  • providersPersonio falls back to HTML scrape when the XML feed is disabled
  • providersPhenom pagination/retry fixes, drop dead auto-detection
  • providersReject numeric entities outside the XML 1.0 Char set
  • providersRoute seven RSS decoders through the shared safe entity decoder, closes #2790
  • providersRoute softgarden and radancy through the shared entity decoder
  • reply-matcherRequire corroboration for partial role-title matches
  • reply-matcherThe '?' unknown-employer placeholder matched everything
  • reply-watchReject unrecognized CLI flags instead of treating them as a path
  • reserve-report-numDo not read a bare date file as a report number, closes #2757
  • role-matcherTokenize non-Latin role titles and scope the mark fold, closes #2781
  • scan-ats-fullCap single-host ATS sweeps at their own concurrency
  • scanLocate the URL anywhere in a pipeline.md entry
  • scanTake the shared lock for scan-history.tsv appends
  • set-statusStop the --role guard from folding every non-Latin title to the same key
  • statesAliases the engine accepts were missing from states.yml
  • statusFold Turkish dotted capitals so uppercase tracker rows resolve to canonical states
  • testsContain a discovered suite that throws at import
  • theme-styleA `$`-pattern in a profile style value splices the body into the CV's
  • updateCommit the index so file-mode changes are not dropped
  • updateIgnore CRLF/LF-only differences when detecting local system edits, closes #2817
  • updateReconcile .gitignore on apply so new ignore rules reach existing installs
  • velocityCount a web-written transition as an observation
  • verify-cv-factsFold allow_metrics through the same noun synonyms
  • verify-cv-factsTreat a period as a thousands separator too
  • voice-dnaMake voice-dna.md private via the template pattern
  • webAdd Grok Build CLI to the web runtime picker
  • webAnalytics tells an offer-holder they have 0 interviews (and nudges them to try harder)
  • webAnchor the fallback stderr classifier so a word can't fail a run
  • webCarry the posted: segment so web evaluations reach the POSTED column
  • webDetect OpenCode in its default install directory
  • webEmit the posting URL in the tracker-additions TSV so web runs join the dedup
  • webEnforce that no runtime grants itself blanket write permission
  • webFinish Unicode company keys for explore + registry
  • webFold Turkish dotted capitals in status keys, and stop hand-copying the state list
  • webKeep Codex JSONL + exit code authoritative for web scoring
  • webLet the pipeline table scroll horizontally instead of clipping on narrow screens
  • webMake the tracker reader agree with parseTrackerRow on row shape
  • webPrevent Codex run jobs from waiting on stdin
  • webRead target_roles with the shape it is actually written in
  • webShow the retry card, not the update-checkout panel, for runtime scan errors
  • webSkip {n}-RESERVED.md sentinels when looking up reports
  • webStop the 16-chip cap from truncating the user's own portals.yml
  • webStrip the author letter from any lettered block, not just A-G
  • webTake the core tracker lock in POST /api/status
  • workdayKey the cap-hit warning on entry provenance, not on --since

Faster

  • analyticsDrop redundant existsSync probes before report reads
  • scanRead each dedup source once per scan run

New

  • webGive the Apply page a way back and a way to record that you applied

Fixed

  • depsMake js-yaml imports work on both 4.x and 5.x
  • depsPatch both HIGH advisories in web (js-yaml 4.3.1, nanoid 3.3.18)
  • depsRaise the js-yaml floor to ^4.3.1 and guard it
  • keysStop the dotted-I fix from collapsing Polish, Lithuanian and Maltese
  • keysStop the Turkish dotted capital from splitting one employer in two
  • scanTake the shared lock for scan-history.tsv appends
  • webAdd Grok Build CLI to the web runtime picker
  • webAnalytics tells an offer-holder they have 0 interviews (and nudges them to try harder)
  • webAnchor the fallback stderr classifier so a word can't fail a run
  • webCarry the posted: segment so web evaluations reach the POSTED column
  • webDetect OpenCode in its default install directory
  • webEmit the posting URL in the tracker-additions TSV so web runs join the dedup
  • webEnforce that no runtime grants itself blanket write permission
  • webFinish Unicode company keys for explore + registry
  • webFold Turkish dotted capitals in status keys, and stop hand-copying the state list
  • webKeep Codex JSONL + exit code authoritative for web scoring
  • webLet the pipeline table scroll horizontally instead of clipping on narrow screens
  • webMake the tracker reader agree with parseTrackerRow on row shape
  • webPrevent Codex run jobs from waiting on stdin
  • webRead target_roles with the shape it is actually written in
  • webShow the retry card, not the update-checkout panel, for runtime scan errors
  • webSkip {n}-RESERVED.md sentinels when looking up reports
  • webStop the 16-chip cap from truncating the user's own portals.yml
  • webStrip the author letter from any lettered block, not just A-G
  • webTake the core tracker lock in POST /api/status

v1.26.0

New

  • coverOptional letter.signature sign-off block, closes #2510
  • cvStrip the Core Competencies section when it has no entries, closes #2509
  • doctorWarn when an API key is overriding the Claude subscription
  • followupRejection-latency signal, courtesy-threshold only
  • invite-matchRecognize rejection emails, not just interview invites
  • ofertaMinimum-wage lawyer question, arithmetic-only
  • ofertaPay-transparency range-width check, self-computed only
  • offer-prepSub-statutory terms route to lawyer, no floors table
  • providersAdd join.com SSR __NEXT_DATA__ parser
  • providersAdd remotli — Swiss remote job board
  • scanAdd getro, consider and joinup zero-auth providers
  • scanMake the pipeline and scan-history paths env-overridable, closes #2271

Fixed

  • a16z-speedrunRetry a transient page failure instead of aborting the whole board
  • arbeitsagenturMove to the v6 Jobsuche API
  • coverFail on an unresolved template token instead of shipping it into the letter
  • cvDrop empty Skills section instead of rendering a bare header
  • cvPair _EMPTY fallbacks with their block so mixed rows stay aligned
  • cvPass a replacer function so $-patterns in candidate text stay literal
  • dedupUse the shared Unicode-aware company key instead of a local ASCII copy
  • dedupWrite the blind-via key prefix as an escape, not a raw NUL byte
  • doctorTreat the cloud billing switches as opt-in, not merely present, closes #2592
  • Extend the backup-file ignore to .npmignore and pin it with a test
  • httpConsolidate duplicated User-Agent strings into a shared module
  • invite-matchNon-Latin company names returned zero candidates
  • jd-skill-gapCRLF-terminated JDs extracted zero skills
  • merge-trackerWrite a lower-scored re-evaluation through instead of discarding it
  • providersHackernews thread lookup filters by the whoishiring tag
  • providersMove The Hub to the v2 jobsandfeatured API
  • providersResize a16z page budgets for the 50-job page size
  • repoAdd .gitattributes so Windows checkouts stop producing whole-file diffs
  • scanRead --company/--posted-after/--posted-before in =value form too
  • scanUnicode-aware keys for role dedup and company matching
  • seedsWalk every YC page instead of stopping after page 1, closes #2525
  • seedsWalk every YC page instead of stopping after page 1
  • update-systemApply .gitattributes before the files it governs
  • webDerive company matching keys from the core, not an ASCII-only copy
  • webRe-read states.yml when it changes instead of caching it for the process lifetime
  • webRoute Today's "See all N" link to the fresh-matches view
  • webTake Write/Edit away from the dashboard's pdf mode

v1.25.0

New

  • Add company:funded — review-first funded-company discovery from public RSS sources
  • cvAdd optional Awards / Honors section to HTML + LaTeX CV templates
  • i18nAdd Italian translations for interview modes
  • pdfOpt-in hiring-manager audit pass — adversarial, research-grounded CV review
  • providersGetManfred board-wide feed (Spanish/EU tech, salaries published)
  • repostsAdd --help usage block to detect-reposts
  • scanAdd --since, a relative posted-date bound that also stops paging early
  • testDynamic upgrade PR gate — old install applies the commit under test
  • webFollow-up Tracker page with logging, history, and cadence settings
  • weekly-digestWeekly interview digest aggregator

Fixed

  • batch-runnerTab-IFS collapse recorded score "-" for every successful offer
  • cli--flag=value was silently ignored in five scripts
  • company-fundedCatch the layoff spellings #2404 left through
  • company-fundedThe cuts N% layoff exclusion never matched
  • company-historyCount a hire as a company response
  • cv-factsThe anti-fabrication gate saw nothing in five shipped locales
  • cv-factsThe employer/title gate only matched lowercase triggers
  • cv-latexSingle mailto: scheme + escape OT1-unsafe glyphs
  • dashboardLocalize the hired status label and buffer split stream openers
  • dashboardThe progress funnel dropped Hired from every stage
  • dedupUse Unicode-aware Via key for blind-employer grouping
  • depsUpdate npm dependencies (+ Dockerfile playwright pins, web lockfile sync)
  • doctorDetect Playwright MCP in JSONC OpenCode configs
  • fingerprintNon-Latin employers no longer collapse to the same company key
  • Git-ignore article-digest.md and guard the user layer against tracking
  • jd-skill-gapWarn when zero skills are classified instead of printing a clean summary
  • livenessClassify transient 5xx as uncertain, not expired
  • merge-trackerCollapse placeholder Notes to the re-eval marker
  • merge-trackerFour silent data-loss paths in the merge loop, with Unicode-safe company matching
  • providersA16z speedrun feed silently truncates to 50 jobs
  • providersDead boards throw instead of reading as live-but-empty
  • Resolve the PDF manifest from the tracker, not the install dir
  • scan-ats-full--since -5 silently scanned nothing and called it a clean run
  • scan-ats-fullKeep the checkpoint when a resolver outage stops a sweep
  • set-statusClose the report-less-row blind spot and add explicit --row/--report selectors
  • Show actual LinkedIn URL as cover-letter link text, not the word "LinkedIn"
  • Strip GitHub URL scheme case-insensitively in cover letters
  • sync-pdfReject unknown options
  • tailorPrompt-cache the openai-tailor.mjs static system prefix
  • test-allThe states.yml freeze guarded 6 of 9 ids
  • testForbid finish() in discovered suites — it forges the global verdict
  • testReport the Windows-unobservable lock contention signal instead of failing
  • testsBudget harness waits for slow runners and preserve crashed-script diagnostics
  • testsFind Git Bash under Scoop and name the fallback shell in failures
  • testsIsolate tracker-columns fixtures from the real reports/ directory
  • testStop test-all silently passing when a node:test suite fails
  • testUse a junction on Windows for the node_modules link
  • trackerNon-Latin company names all keyed to empty string, silently overwriting each other
  • trackerRank Hired in dedup, canonicalize its aliases, stop bare tracker-number merges across roles
  • verify-cv-factsStop the modifier count from deciding whether a claim exists
  • verify-pipelineOrphan check masks and invents orphans
  • verify-pipelineUnicode-aware keys for company/role/Via grouping
  • webRender PDFs from the backend instead of the spawned agent
  • weekly-digest--from=… was silently ignored, digesting the wrong week
  • workableUse the public widget API so large accounts are scanned

Faster

  • detect-repostsBucket titles instead of comparing every pair
  • fingerprintPopcount table + hoisted loop state in findCrossListings
  • testsFix the dead SSRF DNS stub and cut three fixed costs from test-all

v1.24.0

New

  • complianceCheck-table-freshness.mjs — staleness validator for jurisdiction tables (closes #2036)
  • contactsCompany-history.mjs, employer silence and repost facts, closes #1711
  • contactsJob-search phonebook with vCard export
  • cvBlock unsupported employer, title, and tool claims in cover letters
  • cvRecommend CV reuse for similar JDs — deterministic jd-similarity helper
  • doctorCLI-aware Playwright MCP detection + OpenCode config support
  • interview-prepDetect call platform (phone/Zoom/Teams/Meet) from invite text
  • interview-redflagProtected-grounds question detection with jurisdiction table
  • interview/debriefCorrect contradicted facts in the prep file in place
  • interview/planWire in interview-prep's sourced-question research before Block 4
  • interviewDebrief directly from an existing transcript
  • ledgerSet-status transition log + mode wiring
  • oferta/applyImmigration-status requirement overreach — jurisdiction table + posting signal + form warning
  • oferta/applyJurisdiction-prohibited content signal — table + Block G + apply-form warning
  • ofertaAgency licensing check — jurisdiction table + registry pointer for agency-mediated postings (closes #2037)
  • offer-prepJurisdiction-aware restrictive-covenant notes
  • outcomeOutcome recording and application archiving, phase 1
  • portalsStandalone fix-slugs.mjs — auto-write ATS slug fixes to portals.yml
  • providersA16z speedrun talent network board-wide feed
  • providersAdd iCIMS to the reverse-ATS full sweep, closes #2137
  • providersCryptocurrencyjobs — Web3 job board via public RSS, zero-auth
  • radancySupport legacy TalentBrew markup and the JSON results fragment
  • scan-historyAdditive normalized-company column for reliable repost keying
  • scanAdd Playwright scanner for Interamt.de
  • scanCountry-eligibility filter for remote postings, closes #2093
  • scanNegative-cache resolver refusals and stop the sweep on a resolver outage
  • scanPace DNS lookups so a full sweep can't trip a resolver's rate limit
  • statsWire followup-cadence's cold classification into activeApps
  • testSeed-fixture.mjs + era-appropriate install fixtures
  • triageStandalone two-pass triage mode to cut evaluation tokens
  • Versioned application CV artifact schema — bundles with flat-path coexistence

Fixed

  • analyze-patternsUse symbol-safe lookarounds so C++, C# and .NET stop vanishing from tech gaps
  • batchDon't mark a worker-reported failure as completed
  • ciA fork signature's valid check must not go red when the ack comment can't post
  • coverPrevent double comma in achievement bullets
  • dashboardPin the row's own status to the top of the status picker
  • dashboardStop reading funding and valuation figures as Pay
  • dashboardThe 'hired' status renders with no colour in the pipeline list
  • echojobsKeep hybrid roles distinguishable from remote
  • followup-seedAge out an orphaned recover guard so it can't permanently disable stale-lock recovery
  • followupAccept an estimated apply date and report which date the age came from
  • followupRecognise name-only outreach so an empty contact list means no contact
  • jd-skill-gapCanonicalize CV and JD tokens through skill-extract
  • merge-trackerStop sibling-req clobber when the qualifier is a slashed acronym
  • pipeline-lockFloor the ownerless stale check, harden the timeout tests
  • role-matcherFold accented Latin letters before tokenizing role titles, closes #2207
  • scaffolderMaterialize the Kimi skill entrypoint on symlink-less filesystems
  • scanA title-stated remote role survives a city-only location
  • scanIgnore StepStone's volatile rltr param when deduping posting URLs
  • scanPortal-health cross-process lock + resolve PORTAL_HEALTH_PATH from cwd
  • scanRecord auth, server and unknown fetch errors in portal-health instead of reachable
  • testAccept a materialized skill entrypoint, not just a symlink
  • tracker-utils, followup-seedFloor the ownerless stale-lock check so a just-created lock can't be stolen
  • trackerA data row containing --- is invisible to merge-tracker dedup
  • webAdd Hired to the states.ts FALLBACK so the degraded path accepts it
  • webLabel-aware pipeline.md reader — posted:/trust:/note: never misread as columns
  • webPropagate the Hired terminal-success state across the whole dashboard

v1.23.0

New

  • batchAdd batch-tailor.mjs for bulk CV tailoring of high-scoring roles, closes #1836
  • cliAdd Cursor as a supported CLI host
  • cvSupport declarative section HTML partials from disk, closes #2183
  • dashboardAdd a RESPONDED filter tab to the pipeline screen, closes #1999
  • dashboardBuild the pay-span regex from an explicit currency list
  • evalToken-budget-aware context compression for the Gemini and OpenAI evaluators, closes #2077
  • i18nAdd Dutch (nl) modes
  • latex-texSupport resumeItemWithoutTitle bullets and resumeSubItem skills
  • ofertaFlag explicit no-sponsorship as a hard blocker, closes #2016
  • pdfDynamic CSS theming from a profile.yml style block, closes #1837
  • providersAdd Flowxtra board-wide job provider
  • providersAdd VDAB zero-auth provider
  • scanDiscover-ats.mjs — resolve a company list to scannable ATS boards, closes #1864
  • skillsExtract the shared skill tokenizer into skill-extract.mjs
  • upskillLearning plan on the aggregate gap heatmap, closes #1740

Fixed

  • agentic-jobsReplace the broken HTML scraper with the documented REST API, closes #2143
  • agentsCompress AGENTS.md ~20% with zero semantic loss
  • batchUpdate Claude tier mapping to the current model lineup
  • cvAdd GitHub contact link to the HTML CV pipeline
  • dashboardPersist status changes from viewer Discard/SKIP and stale rows
  • dedupMerge notes from removed entries instead of dropping them, closes #1833
  • depsUpdate dependency next to v16.2.11 [security]
  • depsUpdate module golang.org/x/sys to v0.47.0
  • doctorTreat missing user prerequisites as non-fatal setup warnings
  • funnel-velocityCount non-canonical Applied rows in the waiting backlog
  • jd-skill-gapRecognize real-world requirement headers, stop at benefits
  • livenessNormalize typographic punctuation and accents before matching, closes #2162
  • livenessTreat the SPA "has been filled" phrasing as expired, closes #2211
  • match-starTokenize tag matches so short tokens do not substring-collide
  • normalize-statusesUse header-mapped columns instead of fixed indices
  • opencodeAdd missing /career-ops command router, closes #2191
  • patternsRecognize the canonical Hired status in analyze-patterns
  • pdfApply the CV section-order check to non-English CVs
  • pipelineLock appendToPipeline() against concurrent read-modify-write, closes #2188
  • pluginMirror plugin.json at .github/plugin/ for the awesome-copilot validator
  • providersGuard decodeEntities against out-of-range code points
  • reply-matcherDecide rejections before offers to stop mis-typing
  • reply-matcherSanitize domains harvested from tracker notes, closes #2134
  • Restore empty-Certifications section stripping lost in the v1.22.0 refactor, closes #2118
  • Restore the Kimi SKILL.md entrypoint as a real symlink
  • role-matcherStop collapsing leveled variants into the bare title
  • role-matcherStrip the "Member of Technical Staff" prefix before tokenizing, closes #1965
  • role-matcherTreat 'product' as a baseline token so PM sibling specialties stay distinct
  • salary-gapParse US ranges with the currency symbol on both bounds, closes #2190
  • scanKeep body consumption inside the fetch timeout window, closes #2136
  • scanLowercase the path in normalizeUrlForDedup to catch cross-source duplicates
  • scanRecover Greenhouse office cities when location.name is a work model
  • scanWord-boundary location keywords + URL location fallback
  • set-statusFail closed when a lone company row contradicts --role, closes #2009
  • skillRouting drift + discoverable metadata across the agent surface
  • successfactorsPreserve brand path for multi-brand RMK tenants, closes #2010
  • Sync the PDF and scan summary output
  • testMake the SYSTEM_PATHS coverage guard actually run in CI
  • trackerSet SQLite busy_timeout to avoid SQLITE_BUSY under concurrent access, closes #1957
  • trackerSync the PDF column from data/pdf-index.tsv, closes #1429
  • update-systemRollback removes additions left behind under a directory pathspec, closes #2015
  • update-systemVerify the target manifest materialized instead of reporting success, closes #1998
  • verify-cv-factsDetect metric claims the pattern was silently missing
  • webResolve nested postcss and sharp advisories via overrides

Faster

  • scanCache DNS lookups in-process to stop resolver floods, closes #2154

v1.22.0

New

  • cvChinese minimal CV template
  • cvImprove profile-photo configuration and preview
  • expandAdd /expand mode to discover missing CV competencies, closes #1521
  • gemini-evalStatic prefix as systemInstruction for implicit caching
  • i18nSimplified Chinese interview modes (plan/practice/debrief)
  • ofertaBlock G signal 9 — third-party platform location tag mismatch
  • openai-evalHost-gated prompt-cache breakpoint for the static prefix
  • pdfFirst-class zh-CN typography support
  • pdfWarn on rendered page overflow, --strict-pages opt-in hard limit
  • pipelinePer-step token breakdown at end of run
  • providersAdd Alibaba Group careers provider
  • providersAdd Gem scanner provider
  • providersAdd Jobvite zero-auth provider
  • providersAdd Welcome to the Jungle and Agentic Engineering Jobs providers
  • scan--posted-after/--posted-before absolute posting-date filters
  • scanAdd visa_filter for surfacing visa-sponsoring roles, closes #2057

Fixed

  • arbeitsagenturOnly tag nationwide-remote when homeofficetyp is VOLLSTAENDIG
  • Drop stale plugins-registry.json from updater path manifests
  • Honor output language in headless evaluators
  • ollama-evalMove temperature into options where Ollama reads it
  • pdfDrop empty Education section instead of rendering a bare header
  • pdfHarden optional-section boundaries, extract shared cv-sections-core
  • pipelineRecognize #1799 score sentinels in verify-pipeline
  • providersBuild public SmartRecruiters URLs without /postings/
  • scan-ats-fullWire content_filter into reverse scans
  • scanHide unconfigured salary/content filter summaries
  • scanNormalize cosmetic URL variants for dedup
  • scanSeed the company+role dedupe key from all three seen-sources
  • Serialize all tracker writers through the shared lock
  • testKeep discovered suites from terminating the run mid-suite
  • trackerRecognize the Hired canonical status in merge-tracker and stats
  • verify-cv-factsStop a bare '<' from swallowing source evidence

v1.21.0

New

  • applyWarn before reapplying to a repeat company, closes #1920
  • cover-letterSupport --format and --report CLI arguments, closes #1828
  • dashboardManifesto shortcut, help entry and footer link
  • emailAdd confirmed-time no-show follow-up variant, closes #1859
  • interview-prepCross-reference coffee chat notes against interview intel, closes #1940
  • interview-redflagFlag scope/compensation mismatch as a separate fifth dimension, closes #1942
  • interview-redflagSuggest a ready-to-copy blacklist row at Reconsider level, closes #1854
  • interview/planWire the existing Panel Intel table into multi-panelist rounds, closes #1857
  • ledgerImmutable n: ordinal per signature + first-contribution question for new signers
  • livenessAdd Workday to the zero-token ATS liveness API rung
  • ofertaBlock G signal for benefits terminology country mismatch, closes #1935
  • onboardingRoute to the manifesto from the README and the first successful scan
  • pdfAdd role name to the tailored PDF filename for multi-role tracking
  • providersAdd Oracle Recruiting Cloud zero-auth provider
  • reportsUnified Risk Summary block joining the five company-risk signals, closes #1737
  • salary-gapTrack compensation figures stated per interview round, closes #1852
  • scanPersist and surface the scanner trust signal to pipeline and history, closes #1743
  • scanTrack portal health over time and surface coverage decay, closes #1744

Fixed

  • cv-templateKeep role header with its bullets when a location line is present
  • doctorWarn when Node is below 22.5 instead of passing silently, closes #1829
  • envrcOnly load the Nix flake when Nix is installed
  • interview-redflagDrop GitHub PR references from candidate-facing output templates
  • ledger-botMake the first-contribution confirmation copy match what ships
  • ledger-botRestore the 'done' confirmation now that the certificate render is live
  • onboardingRelay the manifesto note in agent-mediated updates
  • pdfDrop empty Projects section instead of rendering a bare header
  • role-matcherKeep base titles distinct from specialized-suffix siblings, closes #1881
  • scan-ats-fullRespect data/blacklist.md, closes #1911
  • scanQuiet dotenv so --json stdout stays parseable, closes #1906
  • Unify atomic report number allocation, closes #1733 #1801 #1835 #1895
  • update-systemAttribute the post-update manifesto link (utm_source=updater)
  • update-systemSurface commit failures instead of silently swallowing them, closes #1844
  • upskillKeep fetched JD text as a string in the targeted --url-text path, closes #1894

v1.20.0

New

  • onboardingSurface the CareerOps Manifesto after updates and setup

Fixed

  • upskillCorrect inverted known-skill suppression in targeted mode

v1.19.0

New

  • batchApply compensation reliability checks to batch workers
  • browser-extractConfigurable jd-mode text cap via --max-chars
  • calibrationFunnel-velocity.mjs — own funnel vs market benchmarks (#1693, part 1)
  • cvFact validator — block invented metrics in generated CVs
  • dashboardAdd Spanish (es) locale to the i18n catalog, closes #1764
  • dashboardDiscard reason picker with learning loop, closes #1380
  • dashboardI18n extraction for the Go TUI (split from #1666)
  • emailATS-broken fallback scenario — recover a stuck application
  • i18nAdd Traditional Chinese (zh-TW) modes
  • i18nChinese salary reliability checks — zh mirror of the compensation tiers
  • img-to-pdfConvert a screenshot into a PDF for ATS uploads
  • interview-prepURL entry path for a role that was never evaluated, closes #1816
  • invite-matchFuzzy-match interview-invite emails to tracker entries
  • Language.output preference — output language decoupled from market modes
  • latexOpt-in latex-tex in-place tailoring of user-owned .tex CVs
  • Make CLAUDE.md a thin @AGENTS.md wrapper — single canonical agent spec
  • modesWire the opt-in CLI extractor into the oferta + auto-pipeline JD paths
  • ofertaBlock G signal 7 — AI-buzzword vs infrastructure mismatch
  • ofertaCompany-type + compensation-reliability tiers in evaluations
  • openrouterPrompt-cache the static system prefix via cache_control
  • pdfDeterministic HTML CV renderer to cut PDF-step token burn
  • pdfJD skill-gap checker before CV generation, zero-LLM, closes #1558
  • pipelineOpenai-tailor.mjs — headless CV tailoring for the no-agent path
  • providers4dayweek auto-detect with spoof-safe host matching (#1657 follow-up)
  • providersAdd LaraJobs zero-auth RSS provider
  • providersAdd Meituan careers provider
  • providersAdd Tencent careers zero-auth provider
  • registryRegister serper and theirstack provider plugins (#1645, #1697)
  • registrySplit plugins-registry.json into per-plugin files
  • reply-watchPaste-reply.mjs manual input path for users without Gmail, closes #1802
  • scanData/blacklist.md — user-owned do-not-apply list
  • scanOpt-in max_posting_age_days freshness gate
  • scanPersist provider postedAt to pipeline and scan-history
  • scanSuppress duplicate roles via company aliases
  • Spend_tier config for model-agnostic model routing + batch pre-screen gate
  • templatesConfig-selectable CV and cover-letter templates
  • trackerAssessment-log.mjs — skills-assessment events with staleness signal
  • trackerRecognize "—"/"-" as valid score-cell N/A sentinels, closes #1799
  • upskillAggregate skill-gap analysis from tracked reports (#1520, phase 1)
  • upskillTargeted single-posting mode with SSRF-guarded fetch, closes #1739

Fixed

  • analyzerResolve report paths relative to the tracker file
  • coverResolve the cover-letter template through the shared resolver
  • Gitignore data/active-interviews.md (user interview data)
  • Ignore logo cache directory
  • livenessTreat off-posting redirects as uncertain, not active
  • Load profile and custom rules deterministically in all mode paths
  • merge-trackerPreserve empty interior cells in tracker-row parsing
  • pdfClean temporary HTML when browser launch fails
  • pdfRender markdown bold in CV summary as (ATS-safe)
  • portalsValidator accepts provider-plugin ids like the runtime does
  • providersSupport explicit api: override for ashby/lever with host-pinned guards
  • reserve-report-numSupport report numbers past 999
  • scanRestore browser-like headers on Workday CXS requests, closes #1811
  • templatesAllowlist the template format to prevent path traversal
  • testNormalize CRLF at read time for doc assertions
  • testsClose CodeQL command-injection findings in the test harness
  • testsSkip web-reader tests when web/ is absent on core-only installs
  • trackerDetect and prevent duplicate tracker # numbers
  • update-systemAdd .claude/hooks/ to USER_PATHS
  • update-systemKeep the updater self-loading to survive old→new re-exec

v1.18.0

New

  • Classify application replies and generate review digest, closes #1585
  • dashboardHired canonical status + job-landed celebration flow
  • i18nAdd German translations of interview modes
  • i18nAdd Hindi language support with dedicated modes and documentation
  • i18nAdd Indonesian (id) modes
  • interview-prepStructured Panel Intel table
  • interviewCompany red-flag detector from transcript signal
  • Match employer reply candidates to application tracker, closes #1584
  • ofertaEmployment classification risk signal in Block G, closes #1630
  • Offer-prep mode — contract reading companion at Offer stage, closes #1608
  • offer-prepNegotiation reply-draft step — draft-only email from Items to raise
  • patternsPer-agency advance-rate analysis from the Via channel
  • pdfAllow intentional CV section reordering via --allow-reorder
  • providersAdd Lever EU instance (jobs.eu.lever.co)
  • providersCornerstone OnDemand (csod) + Rheinmetall
  • providersEchoJobs zero-auth JSON aggregator provider
  • providersPhenom People (phenom) + Radancy TalentBrew (radancy)
  • providersTKMS, Heckler & Koch, and Deutsche Bahn providers
  • registryAdd career-ops-plugin-markdown v0.1.0
  • salaryMode wiring — advertised_comp + observation appends
  • salarySalary-gap.mjs — append-only compensation observation analyzer
  • scanJD-content fingerprinting — flag agency+direct cross-listings, closes #1597
  • scanOpt-in CLI page extractor (browser-extract.mjs)
  • scanPersist per-run scan counters to data/scan-runs.tsv
  • scanScope content_filter per title-category via by_title_keyword
  • scoringCulture-screen dimension with structural capping
  • statsLifetime pipeline stats aggregator
  • Titles mode — suggest adjacent job titles from the CV, closes #1632
  • trackerSet-status.mjs — canonical CLI for tracker status updates, closes #1428
  • trackerVia channel — end employer vs recruiter/agency intermediary

Fixed

  • dashboardDuplicate tracker headers resolve last-occurrence to match JS reader
  • depsUpdate npm dependencies
  • modesEnforce modes/_custom.md overrides across mode files, closes #1618
  • modesWire modes/_custom.md into the read path — house rules were write-only
  • pdfExplain the agentic HTML flow in generate-pdf.mjs usage output
  • Prevent role-matcher from collapsing different seniorities, closes #1616
  • scan-ats-fullReject unrecognized CLI flags with usage help
  • trackerRetrofit remaining positional readers onto the shared header-aware parser
  • updateRaise local git timeout default 30s -> 120s for cloud-evicted trees
  • web44px tap-targets at the component level
  • webContrast tokens — AA across both themes
  • webPortals copy + analytics semantics
  • webUx-audit cleanup — CostBadge global CSS + last sub-44 stragglers

v1.17.0

New

  • Add the opt-in experimental web UI surface (web/) — isolated versioning, CI and packaging
  • add/career-ops add — fetch a project/paper/role into cv.md and article-digest.md
  • agent-inboxQueue requests for the next session
  • applyPre-scan forms for knock-out questions before drafting
  • contactoShort-greeting variant for chat-style outreach
  • emailFormal application email drafts — draft-only, never sends
  • Experimental local-first web UI (opt-in alpha)
  • findResolve a company/role/number query to its full pipeline identity
  • followupSeed a pinned first follow-up when a row turns Applied
  • i18nAdd Korean career-ops modes
  • i18nTranslate interview modes to French, closes #1489
  • i18nTranslate interview modes to Spanish, closes #1490
  • ofertaFlag 'remote' location contradicted by JD-body signals
  • patternsRecruiting-process friction signal at company level
  • patternsTranscript-driven targeting correction (Step 1b) — closes #960
  • pipelineOptional per-offer note in the pipeline writer
  • portalsProbe non-ATS boards through the provider layer
  • profileCandidate contact-channel preference for outreach CTAs, closes #1556
  • providersAdd Get on Board (getonbrd) zero-auth provider
  • providersAmazon (amazon.jobs) and Avature zero-token providers
  • providersAvature self-heals jobOffset→offset pagination
  • providersBeesite (milch & zucker) + softgarden providers
  • providersDassault Systèmes zero-token provider (Exalead XML)
  • providersHonour api: on workday and smartrecruiters
  • providersSAP SuccessFactors (RMK) zero-token provider
  • providersSuccessFactors CSB strategy + bounded health-probe budget
  • registryAdd startup boards plugin
  • reserve-report-num--count N contiguous range reservation
  • scanReport unreachable boards with error classification + doctor sweep
  • verifyDetect duplicate and orphan reports
  • webConfig microcopy humanized (P1.5)
  • webCost affordance — CostBadge muted (P1.6)
  • webDedupe bug reports at write — stable fingerprint + click-gated similar-issue search
  • webEmpty-state free-scan button (P0.1)
  • webExtract cleanChips to a tested module + tab/CR paste delimiter
  • webInbox triage — Abundance → Triage → Shortlist → Opt-in Score
  • webMobile tap-targets ≥44px + FAB clearance
  • webOrange hierarchy — brand-soft Mark-applied + inbox cost legend (P1.4)
  • webReport progressive disclosure (P0.3+P1.8)
  • webRicher bug-report diagnostics — data-shape fingerprint, core version, API errors

Fixed

  • Correctness sweep across tracker, providers, and eval reporting, closes #1527
  • dedupRequire exact company+role match so distinct same-company roles survive
  • infraExempt web/ from the SYSTEM_PATHS coverage guard (isolation contract)
  • merge-trackerDetect TSV score/status column order by header, closes #1427
  • merge-trackerGuard tier-3 fuzzy dedup with req/job number, closes #1524
  • onboardingAuto-copy template seeds in doctor --json (#782, #1369)
  • pathsPrefer cygpath over wslpath in toBashPath()
  • pdfUse CSS @page setup for margins
  • pluginsHarden manifest path containment against symlink traversal
  • Prevent notion plugin from mangling slash-formatted scores
  • providersAvature parser tolerates two live tenant markup variants
  • providersHarden workday pagination against 429s, API caps, and dateless tenants
  • providersUpdate Glints API to v2-alc/searchJobsV3, document Jobstreet GraphQL migration
  • providersWorkday honors ctx.maxPages so the liveness probe stops cleanly
  • scanLoad .env credentials via optional dotenv import
  • updateMake updater timeout budgets configurable
  • updatePreserve local CLAUDE.md additions during /career-ops update
  • updaterAdd .claude/settings.json to USER_PATHS, closes #1408
  • webBump FOLLOW-UPS DUE tap-targets to 44px on mobile
  • webPin turbopack.root to prevent Windows postcss OOM
  • webPoint the 'Get one free' link at the free-AI-engine guide
  • webRestore the report-a-bug kit lost between the RC branch and main

v1.16.0

New

  • Add interview skill modes — plan, practice, debrief
  • applyATS auto-fill for Greenhouse / Ashby / Lever — prepare, don't submit
  • discoverySeed company universe from VC portfolios (YC / a16z)…
  • patternsATS channel yield analysis — algorithmic-monoculture aware
  • pluginsSeed/successor model — community plugins can supersede a bundled reference
  • providersAdd HigherEdJobs RSS provider
  • providersAdd JibeApply provider
  • providersAdd NoDesk provider
  • providersAdd Teamtailor zero-auth RSS provider
  • registryAdd career-ops-plugin-obsidian v0.1.0
  • registryAdd career-ops-plugin-tavily v0.1.0
  • registryAdd google-calendar plugin v0.1.0
  • scanAdd seniority-tier classifier with optional skip_tiers fi…

Fixed

  • cv-templateKeep role titles from orphaning at page breaks
  • dashboardMap tracker columns by header name
  • followup-cadenceSchedule first responded follow-up with responded_initial
  • livenessAdd Ashby API rung so live jobs.ashbyhq.com postings aren't false-expired
  • pdfAnchor the output path-traversal guard to the repo root, not cwd
  • pdfKeep a right gutter so right-aligned CV content isn't clipped
  • pdfThread manifest metadata through render options

v1.15.0

New

  • Add opt-in plugin system (engine + supply-chain governance + registry)
  • Add optional profile photo support for resume template
  • dashboardAdd cover letter hotkey to report viewer
  • dashboardHotkeys to view (d) and regenerate (D) the CV PDF
  • OpenRouter runner — free models, auto-blacklist, no Claude CLI required
  • providersAdd 4 Day Week provider (public zero-auth API)
  • providersAdd Arbeitnow provider
  • providersAdd Hacker News "Who is hiring?" provider (Algolia API)
  • providersAdd Himalayas provider
  • providersAdd Jobicy provider
  • providersAdd Jobspresso provider
  • providersAdd Landing.jobs provider
  • providersAdd Pinpoint ATS provider
  • providersAdd Rippling ATS provider
  • providersAdd The Hub provider
  • providersAdd The Muse provider
  • scanAdd detect-reposts.mjs repost detection from scan-history.tsv
  • scanAdd JustJoin and NoFluffJobs providers
  • scanPersist compensation to pipeline.md
  • scriptsAdd build:dashboard and serve:dashboard npm scripts
  • updaterStructural SYSTEM_PATHS coverage check

Fixed

  • depsUpdate dependency playwright to v1.61.1
  • evalBound research budget to a single-pass query cap
  • scanTighter company matching and dedup order for cooldown filter
  • securityHarden batch tmpfile, PDF output path, and tracker cells
  • trackerShare header-name column mapping across all readers

v1.14.0

New

  • Add modes/_custom.md for user custom instructions
  • applyATS behavioural question matcher from story-bank.md
  • archiveAdd archive-posting.mjs to save live job postings as PDF
  • batchAdd --limit flag + budget guide
  • cliAdd first-class Codex support
  • cliAdd Grok Build CLI support
  • cliRegister Kimi as a supported CLI host
  • cvAdd opt-in profile photo for DACH/European CVs
  • evalAdd openai-eval.mjs for any OpenAI-compatible endpoint
  • modesAdd Danish (da) locale
  • modesAdd EU SWE application calibration mode
  • modesAdd recruiter-side application heuristics
  • ollamaAdd local interactive Ollama evaluator
  • providersAdd Comeet ATS provider
  • providersAdd Personio ATS provider
  • providersAdd WeWorkRemotely RSS provider, closes #1241
  • scanAdd early trust validation and job trust metadata
  • scanPreserve job location in pipeline.md

Fixed

  • batchSingle-worker lock fallback + exit-127 shim-swap retry
  • modesBound subagent delegation to prevent research fan-out, closes #1235
  • pluginDrop non-schema skills/permissions keys from plugin.json
  • scanTrim title-filter keywords before the length check
  • templateScope break-inside to atomic units to prevent CV pagination breaks
  • updaterResolve self-reexec checkout from the import closure, closes #1245

v1.13.0

New

  • arbeitsagenturConfig-driven remoteMatch + server-side homeoffice filter
  • batchAdd --skip-pdf flag to batch-runner.sh
  • dashboardAdd in-viewer status picker overlay
  • dashboardCustomizable columns with column picker
  • dashboardRecognize EUR/GBP/CHF pay and international cities in pipeline derive
  • livenessZero-token ATS API check before Playwright (closes #574)
  • modesAdd Polish (pl) locale modes
  • modesOptional voice-dna.md writing guardrail
  • portalsAdd verify-portals.mjs ATS slug validator
  • providersAdd BambooHR provider
  • providersAdd Breezy HR scanner provider
  • scanAdd --json output, --include-undated, and --shuffle to scan-ats-full
  • trackerAdd `delete --num N` to remove an application row safely

Fixed

  • Auto-create data/pipeline.md and harden Playwright doctor check
  • batchHarden status score handling
  • batchUse awk instead of bc for score math
  • contractExpand interview-prep/* coverage in DATA_CONTRACT
  • dashboardRewrite only the Status cell on status update
  • Images not rendering in PDF output due to about:blank origin
  • Normalize report links from data files
  • providersHarden lever/ashby/workday against SSRF via redirect
  • recruiteeKeep offer URLs on tenant custom domains
  • scanGuard title-filter keyword normalization against malformed config
  • scanMatch short acronym title-filter keywords on word boundaries
  • templateEmit mailto:/tel: links for email and phone in CV header
  • templatesDisable fi/fl ligatures for ATS-clean PDF text extraction

v1.12.0

New

  • batchAdd --status and --watch progress monitoring to batch-runner.sh
  • cliAdd Antigravity CLI compatibility
  • i18nAdd Chinese language modes for China-market job seekers
  • pdfRender Japanese CVs with a lang="ja" CJK font fallback
  • providersAdd Jobstreet and Glints providers for the Indonesian market, closes #1085
  • providersAdd RemoteOK, Remotive, Working Nomads, IBM board providers, closes #1075
  • providersPort Arbeitsagentur to an in-process provider
  • scanAdd content/description filter for providers

Fixed

  • ashbyInclude secondaryLocations so EU-eligible roles surface, closes #1073
  • batchReconcile pipeline.md inbox after batch runs
  • dashboardArchetype regex matches English and Spanish reports
  • dashboardOpen Windows targets without shell
  • dashboardReport last-contact in calendar days, not hours-since-midnight
  • followupResolve report path relative to tracker directory, closes #1070
  • followupUse the real application date from notes, not the eval date
  • geminiValidate evaluation report shape
  • latexLanguage-agnostic section validation + CJK guard
  • merge-trackerRequire company match for number-based dedup, closes #912
  • pdfAuto-install Playwright chromium after update
  • pdfUse ATS-safe system fonts for clean CV text extraction, closes #1074
  • pipelineAdd batch liveness sweep for unconfirmed entries
  • scanSanitize external metadata before writes
  • securityHarden local-parser against command/arg injection and scan-ats against SSRF
  • trackerPreserve notes column when rewriting rows without a trailing pipe
  • updateMaterialize skill entrypoints without symlinks
  • updaterGit-safety on abort + preserve user files on safety-violation rollback

v1.11.0

New

  • Add first-class OpenCode support alongside Claude Code
  • coverAdd optional salutation/greeting to cover letters
  • coverLoad _profile.md so personalization governs the letter
  • doctorWarn when Playwright MCP tools are not configured
  • trackerMap tracker columns by header name
  • trackerSQLite derived index over applications.md — phase 1

Fixed

  • cvAlign certification org column width across rows
  • depsUpdate npm dependencies to v1.61.0
  • evalGate dead links before evaluation in oferta and auto-pipeline
  • generate-pdfInline local fonts as data: URLs so they actually embed
  • merge-trackerSerialize concurrent tracker merges with a filesystem lock
  • pdfWait for load instead of networkidle during render
  • Remove story-bank.md from git tracking
  • skillSurface latex mode in command menus
  • testsRun tracker-mutating scripts with --dry-run in script checks
  • trackerPrevent dedup from deleting distinct same-company roles
  • updateDistribute missing runtime paths
  • updateMatch Release Please component-prefixed tags in version check
  • updateRebuild dashboard binary after Go source changes
  • updateUse target updater manifest during apply

v1.10.0

New

  • applyAdd preflight liveness and role-match gate
  • batchPause batch runner on Claude session limits
  • coverAdd cover letter generation mode
  • cvAdd build-cv-latex.mjs structured JSON to LaTeX renderer
  • dashboardKeep discard reason visible in pipeline preview
  • dashboardSortable Location, Pay, and Last-contact columns in pipeline view
  • Dockerize project for hosts blocked from native Playwright install
  • doctorAdopt doctor --json as the single onboarding state source
  • followupRead cadence settings from profile.yml
  • i18nAdd full Arabic language support and modes
  • modesAdd interactive interview onboarding subcommand
  • scanAdd --rediscover-404 fallback for moved tracked postings
  • scanAdd configurable salary filtering to the zero-token scanner
  • scanAdd portals.yml schema validator
  • scanAdd scan-ats-full.mjs — reverse-discover jobs from public ATS APIs
  • scanAdd scan-history TTL and recheck policy
  • scanAdd SolidJobs provider and job_boards support

Fixed

  • applyPreserve form field contracts
  • batchAppend profile context to worker prompts
  • batchIsolate workers from inherited MCP to prevent parallel deadlock
  • batchStop after min-score skip instead of falling through to completed
  • dashboardResolve tracker-relative report links against the tracker directory, closes #779
  • doctorSingle source of truth for onboarding state via doctor --json
  • flakeDeclare systems so the devShell resolves on macOS, closes #334
  • livenessStop false-expiring postings behind anti-bot walls
  • merge-trackerRequire company match on exact entry-number dedup
  • merge-trackerUse token-union ratio in roleFuzzyMatch to stop cross-role dedup, closes #751
  • patternsParse header-style and Detected-archetype formats in analyze-patterns
  • pdfReject CV section ordering that diverges from cv.md source
  • pipelineAtomic report-number reservation for parallel workers
  • releaseAuto-sync VERSION via release-please generic extra-file
  • releaseSync VERSION file to 1.9.0
  • securityClose SSRF guard bypasses in liveness-browser
  • updateBootstrap tracker-links.mjs and scaffolder/ for v1.8.x to v1.9.0 upgrades
  • updateRun curl version checks concurrently in check()
  • updateUse curl in check() so updates work inside the Claude Code sandbox, closes #754

v1.9.0

New

  • Add npx career-ops scaffolder for one-command install, closes #855
  • Add structured machine summaries to evaluations
  • Add Ukrainian language and market support
  • batchAdd --model flag to batch-runner.sh
  • dashboard/-key live search across pipeline rows
  • i18nAdd Turkish (TR) language modes
  • interview-prepSplit prep by interviewer audience
  • Make PDF auto-generation configurable via auto_pdf_score_threshold
  • scanAdd --verify flag to drop expired postings before pipeline append
  • scanAdd local-parser provider and agent skip rules
  • scanAdd optional always_allow tier to location_filter, closes #650
  • scanAdd Workable, SmartRecruiters, Recruitee ATS parsers, closes #651

Fixed

  • batchWait and retry batch workers on rate limits, closes #505
  • dashboardWidth-aware Markdown rendering with table wrapping in viewer
  • geminiAuto-merge Gemini evals into the tracker instead of a manual-edit reminder
  • Make tracker report links relative to the tracker file
  • pdfDon't spell out ambiguous ¥ currency symbol
  • pdfNormalize arrows, middots, and currency symbols for ATS extraction, closes #730
  • Register the career-ops skill in Claude Code via user_invocable key, closes #763
  • releaseSync VERSION file to 1.8.0
  • scaffolderDon't pre-create user config so agent onboarding triggers, closes #855
  • scanBootstrap providers/ on update + harden greenhouse detect()
  • scanRaise Ashby provider timeout + add backoff retry
  • scanSurface websearch-handoff companies in the run summary, closes #747
  • Scope npm package as @santifer/career-ops
  • update-systemAdd tracker-links.mjs to SYSTEM_PATHS
  • update-systemApply() safety violation reverts cleanly and releases lock
  • update-systemBootstrap liveness-browser.mjs for v1.7→v1.8 upgrades, closes #704
  • update-systemRollback() removes paths absent from backup branch
  • updateDistribute missing modes, locales and CLI configs via update-system
  • updateTimestamp backup branches and roll back to the newest, closes #733

v1.8.0

New

  • scanOptional location_filter in portals.yml + persist location to scan-history

Fixed

  • batchWorkers read modes/_profile.md and config/profile.yml, closes #534
  • depsUpdate dotenv to v17
  • gemini-evalInclude profile.yml and _profile.md in evaluation, closes #617
  • gemini-evalRedact API key from error logs, harden summary parsing
  • gemini-evalSwitch default model to non-deprecated endpoint, surface 429 guidance, closes #614
  • manifestAlign plugin.json skills field with Claude Code plugin schema
  • merge-trackerPreserve short specialty acronyms, require non-baseline overlap, closes #633
  • modesMake /career-ops deep respect user language, not JD language
  • portalsUpdate Weights & Biases entry to CoreWeave acquisition
  • releaseSync VERSION file to 1.7.1
  • scanValidate Greenhouse URL hostname against allowlist to prevent SSRF
  • templatesAlign CV certification rows on a 3-column grid
  • update-systemAllow writing-samples/README.md as system-owned file
  • update-systemBootstrap .agents/ for v1.6→v1.7 migration
  • update-systemDefensive VERSION parsing for release-please marker