Changelog

This changelog lists every career-ops release in plain language. career-ops ships several times a week; the changelog reads straight from GitHub Releases and updates itself. A career-ops update never touches your data — see the Data Contract.

v1.35.0

Latest

New

  • Add Hermes Agent headless CLI support
  • Add reviewed master career profile import
  • cliRegister Pi as a supported CLI host
  • cvOptional professional-title headline slot under the name
  • dashboardAdd posted-date sort mode
  • explorerFree banded title-vs-profile fit hint on discovery cards
  • local-parserPass an optional postedAt through
  • ofertaOpt-in Brazil PcD-quota check (Lei 8.213/91) as a Block A signal
  • patternsReport predicted discard reasons separately
  • pdfAdd optional `context` line to CV experience entries
  • pdfGuard CV work experience against non-chronological order
  • pluginsExpose the canonical posting-URL key through ctx, closes #4218
  • providersAdd applitrack, neogov, redrover and schoolspring for K-12 and college boards
  • providersAdd BambooHR as a 6th scan:full source
  • providersAdd HiringRoom provider (legacy /jobs and JSON-LD /portal/jobs)
  • providersOCC Mundial — Mexico's dominant job board
  • scanAdd Eploy provider
  • scanAdd PeopleSoft Candidate Gateway provider
  • scanAdd PrevueAPS provider (providers/prevueaps.mjs)
  • scanBridge scan-history → discover-ats (auto-propose scanned-but-untracked companies)
  • uiStream matched job cards into results during scan
  • update-systemAdd status command and local_sha to check output
  • validate-profileConfig/profile.yml is never validated, so a misspelled key silently does nothing

Fixed

  • analyze-patternsValidate threshold and vendor flags
  • application-answersFind the draft block by a trailing (draft) marker
  • application-answersParse Block H when its heading is localized
  • avatureRead article--jobs cards, titled from the h3 anchor
  • batch-evaluate_profile.md and tracker-additions resolve to the code root
  • batchFail closed on no-op workers and archive the verbatim JD, closes #4421
  • batchResolve batch-prompt.md placeholders to stable labels
  • Canonical states, data-root paths, pipeline parser, and link regex
  • ciPin the upgrade gate to the main channel so it stays hermetic
  • cliScan-hn.mjs delegates --help and unknown flags to lib/cli-flags.mjs, closes #4598
  • cliValidate scan-interamt flags before a live scan, closes #4599
  • coverFill {{RECIPIENT_BLOCK}} so pack cover templates render
  • dashboardStop level-code digits from shadowing the real Pay figure
  • dashboardTarget the correct tracker file, row, and status cell
  • data-rootGenerate-pdf and set-status resolve the tracker from the code directory
  • data-rootHired-share, reply-watch and paste-reply resolve the configured data root
  • doctorCheckDependencies and checkTrackedBakFiles read the code root
  • doctorMake Git diagnostics locale independent
  • evalDate reports with the local calendar day, not the UTC one
  • followup-cadenceDon't read word-glued #N tags as row cross-references
  • followup-cadenceParseAppliedDate matches gapped ATS phrasing
  • generate-latex--help is read as a filename, and a mistyped flag becomes the output path
  • generate-pdfKey the PDF manifest on report number and artifact kind
  • generate-pdfRecognize Spanish section titles in the section-order guard
  • gitignoreIgnore data/agent-inbox.md
  • gitignoreIgnore symlinked user-layer directories
  • i18nTeach the headed tracker-addition TSV in localized prompts
  • lockClamp the retry backoff to the per-holder deadline
  • merge-trackerA one-sided req number no longer merges into a duplicate row
  • merge-trackerMatch on identical report file, ahead of the company guard
  • merge-trackerReject entry matches across req IDs
  • outcome,trackerStamp the local calendar day, not the UTC one
  • pathsResolve user-layer files via the data root in batch-tailor, cv-templates and openrouter-runner
  • pdfDrop optional sections that arrive as a bare header
  • pdfUse workspace styling for batch and imported renders
  • pipelinePreserve unknown scores when reconciling reports
  • portalsRead the data root's portals.yml in fix-slugs and validate-portals
  • postinstallDrop --with-deps, which fails on non-Debian/Ubuntu Linux
  • providersDetect dead Workday boards via Workday's own maintenance/outage signals
  • providersFilter Pinpoint/Recruitee seeded demo postings
  • providersFold country into the primary location on Ashby, Recruitee and Breezy
  • providersRead greenhouse embed slug, support myworkdaysite boards
  • providersRecruitee joins multi-location offers, drops title-less rows
  • providersRefuse redirects by default in _http.mjs
  • providersRippling switches to the v2 same-origin board API
  • providersSupport MokaHR's international hire-r1.mokahr.com host
  • providersTelegram-channel stops reading a multi-pipe tag as the employer
  • rejection-latencyThe company key deletes combining marks
  • reportsStamp local date in stats.mjs and analyze-patterns.mjs report headers
  • Reserve-report-num.mjs skip batch-state "failed" report numbers
  • role-matcherKeep one-sided level siblings distinct
  • Route zh/zh-TW pipeline report numbering through reserve-report-num.mjs
  • scaffolderRun npm install on Windows without spawning npm.cmd
  • scan-hnReport Gemini errors instead of zero offers
  • scanClose companyMatch corporate-form follow-ups from #3957
  • scanDetect astral word edges in location keywords on Node 26
  • scanFold diacritics on both sides of the title filter
  • scanMigrate scan-runs.tsv onto the current schema
  • scanStrip CJK/Korean corporate-form markers in companyMatch
  • scanStrip pipe-delimited location suffixes from role dedupe keys
  • scriptsResolve user-layer files against the data root, not the checkout
  • set-statusThe canonical tracker write path cannot find a configured tracker
  • statsStop counting failure streaks from portals no longer probed
  • telegram-channelPreserve employer and title fields in hashtag posts
  • testsA killed test run leaves no trap for the next one
  • trackerMigrate missing URL column
  • trackerRecognize localized headers across Node, web, and Go
  • update-systemA preserved directory with an unreadable upstream lookup no longer aborts the whole update
  • upskillAdd testing + observability terms to the skill vocabulary
  • Use model-aware MiniMax context budgets
  • Validate rank pipeline CLI flags
  • validate-portalsWarn on a provider config block that sets no filter
  • verify-atsRecognize section headings in every language the repo ships
  • verify-cv-factsDon't flag a cited posting requirement as a personal metric claim
  • verify-cv-factsStop reading a CV's own reworded prose as a tool claim
  • verify-pipelineDon't flag same company+role reports that carry distinct posting URLs
  • verify-pipelineStop counting a SKIP row as a submission channel
  • verify-portalsReport a live alternate the identity gate refused
  • webThe web tracker reader drops the Apply Link and Follow-up columns
  • workdaySkip the sequential retry when a board hit a structural limit
  • zh-minimalPreserve ATS text extraction order + strip empty certifications section

v1.34.0

New

  • cliAdd --help to cv-sync-check.mjs, closes #3565
  • livenessCheck additional posting URLs through public APIs
  • providersAdd generalist-world board provider
  • providersAdd Python.org Jobs scanner provider
  • providersSupport explicit personio tenant pin
  • readmeREADME v2 with a Sponsors section, welcoming SerpApi as sponsor
  • scanAdd domain-level aggregator repost detection
  • scanOpt-in location_filter.strict fails closed on empty locations
  • statsSuggest portal pruning from observed history
  • update-systemResolve to the latest release tag by default, not main

Fixed

  • agentsStop quoting an injection example that blocks scanner-based hosts
  • Align global score instructions across evaluation paths
  • analyze-patternsAn empty tracker is a new user, not a failed command
  • applyHand off Ashby submission to system browser
  • applyValidate answers against live field limits
  • ashbyRead the salary range from compensationTiers[].components[]
  • audit-portalsLoad providers/ from the checkout, not the data root, closes #4171
  • batchAdd adaptive rate-limit backoff
  • batchEscape ampersands in offer URLs
  • batchGive the worker a Windows-resolvable JD file path under Git Bash
  • batchGive the worker a Windows-resolvable JD file path under Git Bash
  • batchParse scores locale-independently in batch-runner
  • batchReject explicit zero offer limits
  • batchRequire parent confirmation for delegated agency postings
  • browser-extractNormalize JSON-LD length comparison, reset stale title, accept IRI `@type`
  • browser-extractRead schema.org JobPosting when the DOM has no body
  • browser-extractRead schema.org JobPosting when the DOM has no body
  • build-cv-htmlRender each project bullets item as its own block
  • ciCheck out base before running labeler
  • ciPr-triage workflow_run finds fork PRs by head owner:branch, skips main
  • clean-markersAdd -h/--help and reject unrecognized flags
  • cv-latexKeep %, #, ~ and & in CV links, escaped for hyperref
  • dashboardNeutralize control characters in the help-bar flash
  • dashboardStats panels overflow their column, and "evaluated" labels three different numbers
  • dashboardSurface open failures in the UI instead of stderr
  • discover-atsSmartRecruiters' phantom empty board no longer outranks a real not-found
  • doctorFind scan extractor in code checkout
  • followup-cadenceEmit cadenceDefaults when the tracker is empty
  • gitignoreCover reports/ subdirectories, not just the top level
  • gitignoreIgnore node_modules whatever its file type
  • icimsStop doubling the careers- prefix on iCIMS board hosts
  • Improve error message for missing cv.md
  • jd-archiveIgnore report reservation sentinels
  • jd-skill-gapImprove error message for missing cv.md
  • jd-skill-gapRecognize bolded and uncontracted requirements headings
  • livenessInspect embedded ATS before closing posting
  • livenessMove bare "Job Expired" banner to a soft tier + guard closed-loop compounds
  • livenessRecognize "role/position is closed" and bare "Job Expired" banners
  • pdfGive paper size one owner so the CV body and the sheet agree
  • pdfPreserve template text reading order
  • pipelineRoute CV output on cv.output_format instead of the PDF score gate
  • providersAvature preserves facet filters across pages, flags broken parses
  • providersBuild SEEK job links per market host + opt-in appendWorkType
  • providersGive the Lever board feed a 30s timeout, not the 10s default, closes #4177
  • providersMatch inner class tokens and fail loud on unusable generalist-world cards
  • providersOraclecloud drops 12% of a board on a short middle page
  • providersOraclecloud drops 12% of a board on a short middle page
  • providersPass redirect:'error' on deutschebahn requests
  • providersRetry transient aborts in deutschebahn and manfred
  • providersRetry transient aborts in deutschebahn and manfred
  • Resolve MCP config from launch checkout
  • role-matcherSplit one-sided level with two-sided vocabulary gap
  • Run the web test suite on the minimum supported Node
  • scaffolderDo not report "ready" when npm install failed
  • scaffolderDo not report "ready" when npm install failed
  • scanDistinguish unverified zero results
  • scanHonor blacklist domain scope
  • scanKeep same-titled postings apart when their requisitions differ
  • scanRecheck_after_days frees a row, then pipeline.md pins it again
  • scanWarn about stale websearch targeting
  • set-statusAdd --help/-h and list the canonical states in usage
  • templatesHonor profile styles in Chinese Minimal CVs
  • test-allStop flagging 7 files that legitimately credit the maintainer
  • testsSkip web-argv static half when web/ is not installed
  • testsSupport core-only argv contract checks
  • update-systemExempt generated per-application CVs/covers from templates/ prune, closes #3636
  • update-systemKeep an upstream negation ahead of newly appended rules
  • update-systemNever prune a file upstream has not shipped
  • updaterDrop SIGNATURES.md from SYSTEM_PATHS so a new signature stops reading as system drift
  • verifiersResolve provider plugins like the scanner
  • verify-atsBrace the escape for a character above the BMP
  • verify-atsStop the shipped template's own CSS from docking 15 points
  • verify-atsTrim CSS whitespace, so U+00A0 cannot hide a font name
  • verify-cv-factsAlso strip single-asterisk italic emphasis
  • verify-cv-factsConsolidate markdown emphasis stripping (**, __, *)
  • verify-cv-factsRecognize bolded metrics in stripMarkup
  • verify-cv-factsRevert boundary-guarded italic regex, it broke the LaTeX star-command test
  • verify-cv-factsThe fabrication gate read neither its sources nor its config from the data root
  • verify-portals--help no longer falls through to the full network sweep
  • verify-portalsReject a missing or swallowed --file operand
  • web/exploreHonest, configurable scan timeout with partial results
  • webA failed atomic write leaves a full copy of cv.md behind, unignored
  • webMake CLI choices fully clickable
  • workdayResolve "N Locations" placeholders from the detail endpoint

v1.33.0

New

  • batchAdd --cli flag for multi-CLI batch evaluation (opencode, gemini, qwen)
  • browser-extractRead Greenhouse, Lever and Ashby JDs from their public APIs, and add fetch-jd.mjs, closes #2582
  • cvRender an education entry's location on the HTML CV, closes #3773
  • oferta/pdfEnforce JD archival in every report
  • portalsAudit board content, not just reachability
  • providersAdd the Gem Job Board REST API as a verified-URL mode alongside the GraphQL provider
  • providersTelegram-channel, public channel posts via t.me/s/ (zero-auth)
  • scanAdd Collage HR public job provider
  • scanOne machine-findable marker line above every scan summary, closes #3560
  • scanPer-company title_filter_overrides for scan-ats-full.mjs, closes #3708
  • webOpt-in origin allowlist for the local dashboard API
  • wttjServer-side Algolia filters so a scan can be exhaustive

Fixed

  • analysisFunnel-velocity, calibrate and weekly-digest read the configured data root, closes #3714
  • analyze-patternsParse report headers written in French, closes #3807
  • analyze-patternsRead archetype headers from every localized mode, closes #3865
  • check-jd-archiveCredit jds/ captures named by a tracker row
  • check-jd-archiveCredit jds/ captures named by a tracker row
  • check-jd-archiveReject login-wall/404/paywall/JS-shell text as non-content, closes #3829
  • cliValidate analyze-patterns flags through lib/cli-flags.mjs, closes #2979
  • cvRender the ATS template's contact row, closes #3775
  • dashboardServe:dashboard respects CAREER_OPS_DATA_DIR, closes #3924
  • discover-atsA refused redirect is an answer, not a status to re-run
  • doctorDetect project-scoped Playwright MCP plugin installs
  • doctorKeep git's "not a git repository" off stderr in --json, closes #3721
  • doctorMake CLI-resolution tests hermetic against a repo .env
  • evalParse the score in gemini-eval instead of concatenating it, closes #3707
  • evalPersist openai/ollama evaluations as tracker additions
  • followup-cadenceAccept --json, the flag both web follow-up routes pass
  • Four defects invisible in the maintainer's own checkout
  • garenaRoute id encoding through _safe-url so one bad posting drops, not the page
  • gemini-evalWrite the **URL:** report header so its rows reach the URL dedup key, closes #3795
  • gitignoreIgnore the tracker and follow-ups file in the legacy root layout, closes #3717
  • icimsRead every jobLocation entry when picking the location, closes #3727
  • invite-matchExtract company names in any script, not just ASCII, closes #3861
  • invite-matchResolve set-status.mjs from the code root, not the data root
  • invite-matchResolve set-status.mjs from the code root, not the data root
  • jd-skill-gapResolve cv.md against the data root
  • jd-skill-gapResolve cv.md against the data root
  • linkedin-joinUse the real people-search route
  • livenessStop reusing the headed page after its browser closes
  • livenessStop reusing the headed page after its browser closes, closes #4176
  • merge-tracker--help exits early and post-merge hooks resolve from the code root under an external data root
  • merge-trackerA corporate-form merge keeps the row's employer name and prefers an exact company match
  • metaPoint CITATION.cff and package.json at career-ops.org, and stop the blurb drifting across five files
  • ollama-evalStream the response and make num_ctx configurable via OLLAMA_NUM_CTX
  • pdfRecognize Chinese section titles in SECTION_ALIASES, closes #3658
  • plugin-installAdd --help and reject unknown flags
  • providersA lone surrogate in one id/slug no longer aborts the whole page
  • providersA lone surrogate in one id/slug no longer aborts the whole page
  • providersApply default headers case-insensitively
  • providersCoerce before the try; drop tkms encode of the config locale
  • providersPin accept-encoding so zstd bodies are not truncated
  • providersPin accept-encoding so zstd bodies are not truncated
  • providersRadancy stops trusting totalResults, cache-busts JSON, retries every fetch
  • providersRoute feishu-jobs and mokahr id encoding through _safe-url
  • rejection-latencyReport placeholder-employer applications instead of dropping them silently
  • rheinmetallGuard the slug-fallback decode against a malformed percent-escape
  • scanOpt-in location-aware company+role dedupe, closes #3750
  • scanPrioritize configured locations in Workday facet recovery, closes #3850
  • templatesMake the CV template's second hardcoded color themeable, closes #3695
  • test-allDiscovered-suite guards ignore calls mentioned only in comments
  • test-allDiscovered-suite guards ignore calls mentioned only in comments
  • testsGuard subtree-anchored walkers against nested checkouts
  • testsPass --confirm to apply in the local-paths regression leg
  • testsSkip nested checkouts by marker, not by the name .git, closes #3499
  • tkmsRe-encode the config locale, hoisted out of the row loop to fail loud
  • token-trackerAdd MiniMax-M3 and MiniMax-M2.7 rates
  • trackerCarry the tracker layout through the export round-trip, closes #3703
  • trackerMap "fecha" to the date column, closes #3705
  • trackerResolve addition columns by name so score and status cannot transpose
  • trackerStrip invisible control characters at the cell sanitizer, closes #3892
  • triageWeights sum to 1.00 and a test pins prose against the formula, closes #3738
  • updateResolve preserved files before staging so :(exclude) never reaches --literal-pathspecs, closes #3740
  • url-keyPreserve existing fragment comparison params
  • url-keyPreserve hash-route posting identity
  • url-keyPreserve hash-route posting identity
  • verify-cv-factsA proposed plan horizon is not a metric claim
  • verify-cv-factsRequire a real word, not a bare capital letter, for a title claim, closes #3907
  • verify-cv-factsStop flagging ordinary prose as tool claims, closes #3639
  • verify-cv-factsTell a disabled fact gate apart from one that ran clean, closes #3894
  • webDetect a real tailored CV/cover on disk, not just the tracker flag
  • webDon't let a failed fetch become a scored report
  • webFence agent CLIs at the spawn boundary
  • webGive grok a parser, and make the token fold per-CLI
  • webIdentify the verdict block by its heading, not by the letter
  • webParseCliJson misses set-status.mjs's pretty-printed success
  • webResolve the tailored cover for THIS application, not the company's newest
  • workdayTag a split whose chosen facet under-covers the board

v1.32.0

New

  • discardAdd discard-log analytics and tuning summary, closes #3392
  • ofertaAdd evidence-tiered requirement importance to Block B
  • pluginAdd h1b-sponsor for DOL sponsorship history on US roles
  • providersAdd Built In aggregator provider
  • providersAdd Feishu Jobs and MokaHR scanner providers
  • providersAdd Garena careers provider
  • scanAdd a durable machine-readable scan receipt
  • scanRemember permanently dead ATS boards, closes #2840
  • templatesCJK support for the LaTeX/Overleaf CV path via tectonic, closes #3553
  • updaterRequire confirmation before installation, closes #2865

Fixed

  • agent-inboxLock resolve rewrites so a concurrent add is never dropped, closes #3478
  • analyze-patternsStop counting Applied as positive
  • calibrateResolve the tracker colmap from the line array, not the header line, closes #3495
  • cvBlock delegated authorship escalation
  • cvReject CV payloads whose section keys the builders never read, closes #3523
  • dashboardMatch company slugs at hyphen boundaries so Meta cannot open Metabase's CV
  • data-rootResolve templates/states.yml from the codebase, not the data root
  • emailAlign fit points with the tailored CV via the pdf-index row, closes #3460
  • fact-gateCount education and training nouns as metrics
  • funnel-velocityFold status-log history into calibration rates, closes #3493
  • geminiResolve encoding mojibake on Windows and route localized modes
  • gitignoreThe tracker's derived SQLite index is unignored outside data/
  • gmailSkip page assets so logos stop landing as job leads
  • Harden context budget prompt assembly
  • invite-matchStop extractReqId backtracking quadratically
  • jd-skill-gapRecognize Traditional and Simplified Chinese requirement headings
  • merge-trackerA corporate-suffix variant is the same employer, closes #3665
  • merge-trackerTwo '?' rows with no Via silently merge, overwriting one, closes #3410
  • ofertaLead Block B with the decisive columns and freeze their order
  • openai-evalStream the evaluation call instead of a single buffered response
  • openrouterWrite scan-history and pipeline through the shared locked writers
  • pdfAccept the canonical modes/pdf.md tailoring order in validateCvSectionOrder
  • pdfRun the fact gate before rendering a CV
  • pluginsA YAML typo in plugins.yml no longer destroys the whole config, closes #3592
  • portalsSweep and validate job_boards, not only tracked_companies
  • reply-matcherA partial role-word match must be a whole word
  • reserve-report-numHandle --help/-h explicitly
  • role-matcherA level stated on both sides of a title must agree
  • scaffolderRestore the published npm package name
  • scan-ats-fullCollapse a Workday requisition served under several sites of one tenant
  • scan-ats-fullSend the progress counter to stderr under --json
  • scanDo not block Dublin OH as Ireland
  • scanResolve scanner user data against the data root, not the cwd, closes #3510
  • set-statusA transition into Applied seeds the follow-up from set-status itself, closes #3459
  • skill-extractRecognize marketing/GTM skills and stop reporting tracked employers as gaps
  • templatesHonor profile font_family in the Traditional Chinese CV block, closes #3154
  • templatesKeep CJK fallback fonts active for ja, zh-CN and ko
  • testsAnswer gitignore probes that cross a user-layer symlink
  • testsStop the photo suite writing cv-preview.html into the user's data root
  • trackerReject malformed application IDs instead of coercing them
  • trackerResolve templates/states.yml from the module, not the cwd, closes #3508
  • trackerResolve the derived index path at call time, not at import
  • trackerSort the applications table by # ascending on write
  • triageFall back to Playwright when WebFetch finds nothing
  • update-systemApply() cannot commit when a path it stages is ignored or never tracked
  • updatePoint the updater at the repository's new home
  • updaterBack up self-bootstrap edits before checkout
  • updaterScope commits to shipped files
  • verify-cv-factsBind a count to the nearest metric noun, not the farthest
  • web,dashboardPoint two user-facing references at the repository's new home
  • webA company with no usable slug must not match every tailored CV
  • webEnable apply from the generated pdf index
  • webFind Grok in its default install dirs, not only on PATH
  • webOrder the Today action queue before truncating it
  • webPreserve a malformed portals.yml instead of overwriting it with the example
  • webRank "Awaiting your decision" by every EVALUATED alias, not an English prefix
  • webRequire the cv- prefix so the tailored-CV resolvers stop returning the cover letter
  • webResolve the tailored CV for THIS application, not the newest for the company
  • webSelf-host the production fonts so the app starts without Google
  • webTell the beta reporter's user when the dupe search could not run
  • workdayRecover offset-clamped tenants with a facet split
  • workdayResolve a CXS-form URL as the endpoint, not as a careers page

v1.31.0

New

  • application-answersRead the evaluation's Block H draft answers
  • cvAdd "text" output_format — tailored markdown CV, no PDF
  • cvATS-friendliness check — score a generated CV for parseability
  • External data directory via CAREER_OPS_ROOT — lands #1444
  • hired-wallA quiet chevron with the exact remainder says the strip continues
  • hired-wallThe audit line speaks to the person mid-search
  • hired-wallThe badge is the title — self-identifying label, own share line, tighter audit line
  • portalsProfession-agnostic examples in portals.example.yml
  • providersJobsDB Hong Kong via the existing jobstreet provider
  • webAdd a global "Back to Top" button
  • Wire reply-watch into status-log.tsv

Fixed

  • coverageExclude the local-paths declaration file so a fork can commit it
  • cv-sync-checkResolve prompt paths from CODE_ROOT instead of an undefined projectRoot
  • cv-sync-checkStop allowFail from excusing an uncaught crash
  • dashboardRead job URLs from the tracker before the legacy enrichment tiers
  • depsRefresh web lockfile for Next update
  • doctorSurvive a null entry in installed_plugins.json
  • harnessMake the syntax gate recursive, shared with npm run lint
  • hired-shareSuggest outcome.mjs's real syntax in the no-Hired-row error
  • providers/icimsFill a missing location from the posting's JSON-LD
  • scanLevel 1 runs Playwright sequentially, matching the shared-session rule
  • scanOpt-in word:/stem: anchoring for content_filter keywords
  • testsScope the profile pin and move the last hand-registered suites
  • update-systemRefuse to run when the install is not its own git toplevel
  • updaterParse git status with -z so quoted paths and renames match real files
  • verify-pipelineRecover a report number from a link target written with backslashes
  • webHonour language.modes_dir and language.output on web-triggered runs
  • webIgnore nonfatal CLI stderr on clean run exit
  • webOnly surface follow-ups that are actually due
  • webRegenerate the nested web/ lockfile on postcss bumps
  • webShow a cause-specific hint on job failure instead of an always-auth prompt
  • webShow Via attribution for confidential employers
  • webStop evaluation tables collapsing to one word per line
  • webStop tracing runtime data paths
  • webTab label spacing and report table word-breaking
  • webUse next/link for decision-card report link

v1.30.0

New

  • Add /calibrate — check evaluation scores against real outcomes
  • applyRecover previous answers through --read --strict at the CLI seam
  • artifactsATS form copy-paste plain-text exporter
  • Clean-markers — audit/strip hidden Unicode from generated text outputs
  • cliAdd help flags to check-liveness
  • cliApplication-artifacts.mjs honours --help
  • communityPR adoption ladder for quiet PRs
  • communityThe Hired Wall, a verifiable ledger of people hired with career-ops
  • cvAdd optional Interests section to the HTML CV template
  • doctorDetect personalization files still carrying template content
  • hired-wallAnonymous cards carry sector · location, mirroring the credited-card hierarchy
  • hired-wallVerified-hires framing, one CTA line, anonymous silhouette, months parsing
  • outcomeAdd --clean-output to archive-then-remove tailored CVs
  • pluginsRegister career-ops-plugin-xquik (X hiring posts via Xquik, BYO-key)
  • providers/getonbrdScan multiple categories per entry
  • providersAdd ITviec provider — first Vietnamese job source
  • providersAdd Torre opportunity-search provider
  • providersCareerViet, second Vietnamese job source
  • templatesAdd ATS-friendly single-column CV template pack
  • templatesDiscover template packs by name
  • title-filterA stem: prefix, for the half a plain keyword gives away

Fixed

  • browser-extractRead Workday JDs from the CXS API, and fail loudly on an empty JD
  • build-cv-latexRender markdown bold in bullets as \textbf
  • calibrateRead all 14 outcome spellings outcome.mjs writes
  • cliValidate flag values in detect-reposts via the shared safeIntFlag
  • contactoStop searching for contacts the mode never uses
  • cv,pdfAddress CodeRabbit review feedback for #2213
  • datesWeekly-digest and rejection-latency read the local day, not the UTC day
  • doctorSurface tracked .bak backup files as a warning
  • fact-gateA non-English CV inflating headcount returns 'pass' — say so instead
  • followupStop reporting the candidate's own address as a contact to chase
  • followupStop truncating plus-addressed emails at the plus
  • gfi-claimsReply when /assign is used outside the claim pool
  • Handle quoted angle brackets while stripping HTML tags
  • hired-wallEllipsize single-line card rows instead of clipping at the viewBox
  • hired-wallHonor both permission wordings and default public stories to full credit
  • i18nPreserve safety guardrails in localized modes
  • jobbankcaCount raw entries for pagination
  • merge-tracker--backfill-urls rebuilds unfillable rows to full header width
  • outcomeA tracker edit forks the append-only journal, and directory order decides which half counts
  • pdfEnforce workspace boundary in direct renderer
  • pdfRun the CLI when reached through a symlink
  • pipelineUse browser-first LinkedIn extraction
  • pluginsIsolate cmdRun results to the requested plugin id
  • pluginsScale export hook timeout with tracker size
  • portals.exampleDrop retired EchoJobs block
  • providersA16z treats a non-positive total_pages as absent, not as one page
  • providersTotal_pages outranks a short page in the a16z sweep loop
  • reconcile-pipelineValidate CLI flags via the shared helper
  • Resolve skill paths from project root
  • salary-gapDecide which separator is the decimal point before deleting either
  • scanThree scanners stamp first_seen in UTC, the reader measures it in local
  • stats,calibrateLedger-aware funnel + calibration (#1428, #1724)
  • stats,calibrateReject malformed status ledger rows
  • statsStop reporting a neighbouring counter when scan-runs.tsv drifts
  • story-provenanceMake the context matcher script-aware, not ASCII-only
  • update-systemNever prune a file the update just preserved, or an asset it references
  • updateDrop the duplicate prune loop that deleted stale files twice
  • verifyA check that could not run is a failure, not a warning
  • webClassify a tracker-lock filesystem failure as itself, not as contention
  • webKey company logos with the Unicode-aware normalizer so non-Latin names don't collide
  • webSalvage truncated JSON at each prefix's own depth, not one global pad
  • webStop hiding an employer's whole board after one evaluation
  • webStop killing evaluate runs at 285s and misreporting the kill

v1.29.0

New

  • anti-fabricationTier the Source-of-Truth boundary and add story-provenance-check
  • contactsLinkedin-join.mjs — warm-intro finder from a LinkedIn connections export
  • cvOptional url support for projects in HTML and LaTeX
  • detect-repostsSkip multi-employer aggregator boards, and say why
  • pdfDeclare CV section order in config/profile.yml
  • providersAdd jobbankca, Canada's federal Job Bank
  • providersJob.description for recruitee, ashby, and opt-in smartrecruiters
  • providersMycareersfuture, Singapore's national job bank
  • scanAdd Hacker News scanner with optional AI enhancement
  • scanOpt-in anchored keyword matching
  • verify-pipelineFlag a malformed follow-ups.md instead of reading it as empty
  • webRestrict the local dashboard API to same-origin and loopback

Fixed

  • add-entryDelegate flag validation to shared validateFlags
  • agent-inboxSeed the queue under the lock, not before it
  • ashbyStop retrying a permanent failure, and honour a clamped Retry-After
  • ashbySurface remote work model in the location string
  • batchKeep JD word count machine-readable under FORCE_COLOR
  • classify-tierAssociate + an academic rank is not entry-level
  • cliClose the missing-operand hole for value-taking flags
  • cliValidate browser-extract flags and honour both value forms
  • cliValidate fix-slugs flags
  • cvHonor Korean profile font theme
  • datesSeven more today-gates resolve in UTC
  • depsUpdate web npm dependencies (major)
  • detect-repostsConcurrent openings were reported as reposts
  • followup-cadenceValidate CLI flags via the shared helper
  • greenhousePopulate job.description from the boards API content field
  • livenessA dead third-party host must not poison the whole verdict
  • livenessAdd a LinkedIn rung so LinkedIn postings get a real verdict
  • locksOne recovery judgment, imported by all three copies
  • locksShare the waiting half of the protocol with the three lock copies
  • pdfName both sides when the lexical containment check fires
  • pdfName canonicalization failure separately from a real workspace escape
  • pdfStop the batch-evaluate fixture leaking its tracker env
  • pipeline-lockA vanished lock is not a lock you may delete
  • pipeline-lockCarry the judged directory's identity to the rm
  • pluginsDiscover a plugin directory that is symlinked into a plugin root
  • portals.exampleName the support ROLE, not the whole domain
  • providers/leverFold categories.allLocations into location
  • providersRetire echojobs, feed is gone behind bot protection
  • providersValidate resolved addresses before connecting (DNS rebinding guard)
  • rename-syncMigrate 5 vulnerable call sites to renameSyncWithRetry
  • salary-gapTreat a period as thousands grouping, not a decimal point
  • set-statusResolve --report links from the Notes cell on customized layouts
  • templatesExtend profile font_family override to ja and zh blocks
  • templatesKeep a project's tech line with the description above it
  • testsAssert flag echo by substring, not by unescaped RegExp
  • testsAssert the flag echo with includes instead of an unescaped RegExp
  • testsGuard the web/ mirror import behind existsSync
  • testsKeep the end of a failing script's output, not just the head
  • testsMake the suite symlink-aware for externalized user layers
  • updateRefuse non-canonical paths in the local declaration file
  • updaterParse the SYSTEM_PATHS array instead of scraping it with a regex
  • updaterSettle same-version SHA mismatch on tree content, not SHAs
  • updateStop misreading upstream's own content as a local edit
  • verify-portalsDecode the HTML entities a board page serves in its title
  • verify-portalsStop the slug repair path adopting a stranger's board
  • webGive the methodology link a real tap target and a new-tab cue
  • webKeep child stderr out of the status response on the crash path
  • webKeep the query string in the Explore dedup key so distinct postings don't collapse
  • webKeep the run stream alive during silent agent phases
  • webReport the uncapped weekly match count while keeping the render bounded
  • webStamp pipeline first_seen with the local day, not UTC

v1.28.0

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