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
LatestNew
- Add Hermes Agent headless CLI support
- Add reviewed master career profile import
cliRegister Pi as a supported CLI hostcvOptional professional-title headline slot under the namedashboardAdd posted-date sort modeexplorerFree banded title-vs-profile fit hint on discovery cardslocal-parserPass an optional postedAt throughofertaOpt-in Brazil PcD-quota check (Lei 8.213/91) as a Block A signalpatternsReport predicted discard reasons separatelypdfAdd optional `context` line to CV experience entriespdfGuard CV work experience against non-chronological orderpluginsExpose the canonical posting-URL key through ctx, closes #4218providersAdd applitrack, neogov, redrover and schoolspring for K-12 and college boardsprovidersAdd BambooHR as a 6th scan:full sourceprovidersAdd HiringRoom provider (legacy /jobs and JSON-LD /portal/jobs)providersOCC Mundial — Mexico's dominant job boardscanAdd Eploy providerscanAdd PeopleSoft Candidate Gateway providerscanAdd PrevueAPS provider (providers/prevueaps.mjs)scanBridge scan-history → discover-ats (auto-propose scanned-but-untracked companies)uiStream matched job cards into results during scanupdate-systemAdd status command and local_sha to check outputvalidate-profileConfig/profile.yml is never validated, so a misspelled key silently does nothing
Fixed
analyze-patternsValidate threshold and vendor flagsapplication-answersFind the draft block by a trailing (draft) markerapplication-answersParse Block H when its heading is localizedavatureRead article--jobs cards, titled from the h3 anchorbatch-evaluate_profile.md and tracker-additions resolve to the code rootbatchFail closed on no-op workers and archive the verbatim JD, closes #4421batchResolve 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 hermeticcliScan-hn.mjs delegates --help and unknown flags to lib/cli-flags.mjs, closes #4598cliValidate scan-interamt flags before a live scan, closes #4599coverFill {{RECIPIENT_BLOCK}} so pack cover templates renderdashboardStop level-code digits from shadowing the real Pay figuredashboardTarget the correct tracker file, row, and status celldata-rootGenerate-pdf and set-status resolve the tracker from the code directorydata-rootHired-share, reply-watch and paste-reply resolve the configured data rootdoctorCheckDependencies and checkTrackedBakFiles read the code rootdoctorMake Git diagnostics locale independentevalDate reports with the local calendar day, not the UTC onefollowup-cadenceDon't read word-glued #N tags as row cross-referencesfollowup-cadenceParseAppliedDate matches gapped ATS phrasinggenerate-latex--help is read as a filename, and a mistyped flag becomes the output pathgenerate-pdfKey the PDF manifest on report number and artifact kindgenerate-pdfRecognize Spanish section titles in the section-order guardgitignoreIgnore data/agent-inbox.mdgitignoreIgnore symlinked user-layer directoriesi18nTeach the headed tracker-addition TSV in localized promptslockClamp the retry backoff to the per-holder deadlinemerge-trackerA one-sided req number no longer merges into a duplicate rowmerge-trackerMatch on identical report file, ahead of the company guardmerge-trackerReject entry matches across req IDsoutcome,trackerStamp the local calendar day, not the UTC onepathsResolve user-layer files via the data root in batch-tailor, cv-templates and openrouter-runnerpdfDrop optional sections that arrive as a bare headerpdfUse workspace styling for batch and imported renderspipelinePreserve unknown scores when reconciling reportsportalsRead the data root's portals.yml in fix-slugs and validate-portalspostinstallDrop --with-deps, which fails on non-Debian/Ubuntu LinuxprovidersDetect dead Workday boards via Workday's own maintenance/outage signalsprovidersFilter Pinpoint/Recruitee seeded demo postingsprovidersFold country into the primary location on Ashby, Recruitee and BreezyprovidersRead greenhouse embed slug, support myworkdaysite boardsprovidersRecruitee joins multi-location offers, drops title-less rowsprovidersRefuse redirects by default in _http.mjsprovidersRippling switches to the v2 same-origin board APIprovidersSupport MokaHR's international hire-r1.mokahr.com hostprovidersTelegram-channel stops reading a multi-pipe tag as the employerrejection-latencyThe company key deletes combining marksreportsStamp 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.cmdscan-hnReport Gemini errors instead of zero offersscanClose companyMatch corporate-form follow-ups from #3957scanDetect astral word edges in location keywords on Node 26scanFold diacritics on both sides of the title filterscanMigrate scan-runs.tsv onto the current schemascanStrip CJK/Korean corporate-form markers in companyMatchscanStrip pipe-delimited location suffixes from role dedupe keysscriptsResolve user-layer files against the data root, not the checkoutset-statusThe canonical tracker write path cannot find a configured trackerstatsStop counting failure streaks from portals no longer probedtelegram-channelPreserve employer and title fields in hashtag poststestsA killed test run leaves no trap for the next onetrackerMigrate missing URL columntrackerRecognize localized headers across Node, web, and Goupdate-systemA preserved directory with an unreadable upstream lookup no longer aborts the whole updateupskillAdd 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 filterverify-atsRecognize section headings in every language the repo shipsverify-cv-factsDon't flag a cited posting requirement as a personal metric claimverify-cv-factsStop reading a CV's own reworded prose as a tool claimverify-pipelineDon't flag same company+role reports that carry distinct posting URLsverify-pipelineStop counting a SKIP row as a submission channelverify-portalsReport a live alternate the identity gate refusedwebThe web tracker reader drops the Apply Link and Follow-up columnsworkdaySkip the sequential retry when a board hit a structural limitzh-minimalPreserve ATS text extraction order + strip empty certifications section
New
cliAdd --help to cv-sync-check.mjs, closes #3565livenessCheck additional posting URLs through public APIsprovidersAdd generalist-world board providerprovidersAdd Python.org Jobs scanner providerprovidersSupport explicit personio tenant pinreadmeREADME v2 with a Sponsors section, welcoming SerpApi as sponsorscanAdd domain-level aggregator repost detectionscanOpt-in location_filter.strict fails closed on empty locationsstatsSuggest portal pruning from observed historyupdate-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 commandapplyHand off Ashby submission to system browserapplyValidate answers against live field limitsashbyRead the salary range from compensationTiers[].components[]audit-portalsLoad providers/ from the checkout, not the data root, closes #4171batchAdd adaptive rate-limit backoffbatchEscape ampersands in offer URLsbatchGive the worker a Windows-resolvable JD file path under Git BashbatchGive the worker a Windows-resolvable JD file path under Git BashbatchParse scores locale-independently in batch-runnerbatchReject explicit zero offer limitsbatchRequire parent confirmation for delegated agency postingsbrowser-extractNormalize JSON-LD length comparison, reset stale title, accept IRI `@type`browser-extractRead schema.org JobPosting when the DOM has no bodybrowser-extractRead schema.org JobPosting when the DOM has no bodybuild-cv-htmlRender each project bullets item as its own blockciCheck out base before running labelerciPr-triage workflow_run finds fork PRs by head owner:branch, skips mainclean-markersAdd -h/--help and reject unrecognized flagscv-latexKeep %, #, ~ and & in CV links, escaped for hyperrefdashboardNeutralize control characters in the help-bar flashdashboardStats panels overflow their column, and "evaluated" labels three different numbersdashboardSurface open failures in the UI instead of stderrdiscover-atsSmartRecruiters' phantom empty board no longer outranks a real not-founddoctorFind scan extractor in code checkoutfollowup-cadenceEmit cadenceDefaults when the tracker is emptygitignoreCover reports/ subdirectories, not just the top levelgitignoreIgnore node_modules whatever its file typeicimsStop doubling the careers- prefix on iCIMS board hosts- Improve error message for missing cv.md
jd-archiveIgnore report reservation sentinelsjd-skill-gapImprove error message for missing cv.mdjd-skill-gapRecognize bolded and uncontracted requirements headingslivenessInspect embedded ATS before closing postinglivenessMove bare "Job Expired" banner to a soft tier + guard closed-loop compoundslivenessRecognize "role/position is closed" and bare "Job Expired" bannerspdfGive paper size one owner so the CV body and the sheet agreepdfPreserve template text reading orderpipelineRoute CV output on cv.output_format instead of the PDF score gateprovidersAvature preserves facet filters across pages, flags broken parsesprovidersBuild SEEK job links per market host + opt-in appendWorkTypeprovidersGive the Lever board feed a 30s timeout, not the 10s default, closes #4177providersMatch inner class tokens and fail loud on unusable generalist-world cardsprovidersOraclecloud drops 12% of a board on a short middle pageprovidersOraclecloud drops 12% of a board on a short middle pageprovidersPass redirect:'error' on deutschebahn requestsprovidersRetry transient aborts in deutschebahn and manfredprovidersRetry 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 failedscaffolderDo not report "ready" when npm install failedscanDistinguish unverified zero resultsscanHonor blacklist domain scopescanKeep same-titled postings apart when their requisitions differscanRecheck_after_days frees a row, then pipeline.md pins it againscanWarn about stale websearch targetingset-statusAdd --help/-h and list the canonical states in usagetemplatesHonor profile styles in Chinese Minimal CVstest-allStop flagging 7 files that legitimately credit the maintainertestsSkip web-argv static half when web/ is not installedtestsSupport core-only argv contract checksupdate-systemExempt generated per-application CVs/covers from templates/ prune, closes #3636update-systemKeep an upstream negation ahead of newly appended rulesupdate-systemNever prune a file upstream has not shippedupdaterDrop SIGNATURES.md from SYSTEM_PATHS so a new signature stops reading as system driftverifiersResolve provider plugins like the scannerverify-atsBrace the escape for a character above the BMPverify-atsStop the shipped template's own CSS from docking 15 pointsverify-atsTrim CSS whitespace, so U+00A0 cannot hide a font nameverify-cv-factsAlso strip single-asterisk italic emphasisverify-cv-factsConsolidate markdown emphasis stripping (**, __, *)verify-cv-factsRecognize bolded metrics in stripMarkupverify-cv-factsRevert boundary-guarded italic regex, it broke the LaTeX star-command testverify-cv-factsThe fabrication gate read neither its sources nor its config from the data rootverify-portals--help no longer falls through to the full network sweepverify-portalsReject a missing or swallowed --file operandweb/exploreHonest, configurable scan timeout with partial resultswebA failed atomic write leaves a full copy of cv.md behind, unignoredwebMake CLI choices fully clickableworkdayResolve "N Locations" placeholders from the detail endpoint
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 #2582cvRender an education entry's location on the HTML CV, closes #3773oferta/pdfEnforce JD archival in every reportportalsAudit board content, not just reachabilityprovidersAdd the Gem Job Board REST API as a verified-URL mode alongside the GraphQL providerprovidersTelegram-channel, public channel posts via t.me/s/ (zero-auth)scanAdd Collage HR public job providerscanOne machine-findable marker line above every scan summary, closes #3560scanPer-company title_filter_overrides for scan-ats-full.mjs, closes #3708webOpt-in origin allowlist for the local dashboard APIwttjServer-side Algolia filters so a scan can be exhaustive
Fixed
analysisFunnel-velocity, calibrate and weekly-digest read the configured data root, closes #3714analyze-patternsParse report headers written in French, closes #3807analyze-patternsRead archetype headers from every localized mode, closes #3865check-jd-archiveCredit jds/ captures named by a tracker rowcheck-jd-archiveCredit jds/ captures named by a tracker rowcheck-jd-archiveReject login-wall/404/paywall/JS-shell text as non-content, closes #3829cliValidate analyze-patterns flags through lib/cli-flags.mjs, closes #2979cvRender the ATS template's contact row, closes #3775dashboardServe:dashboard respects CAREER_OPS_DATA_DIR, closes #3924discover-atsA refused redirect is an answer, not a status to re-rundoctorDetect project-scoped Playwright MCP plugin installsdoctorKeep git's "not a git repository" off stderr in --json, closes #3721doctorMake CLI-resolution tests hermetic against a repo .envevalParse the score in gemini-eval instead of concatenating it, closes #3707evalPersist openai/ollama evaluations as tracker additionsfollowup-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 pagegemini-evalWrite the **URL:** report header so its rows reach the URL dedup key, closes #3795gitignoreIgnore the tracker and follow-ups file in the legacy root layout, closes #3717icimsRead every jobLocation entry when picking the location, closes #3727invite-matchExtract company names in any script, not just ASCII, closes #3861invite-matchResolve set-status.mjs from the code root, not the data rootinvite-matchResolve set-status.mjs from the code root, not the data rootjd-skill-gapResolve cv.md against the data rootjd-skill-gapResolve cv.md against the data rootlinkedin-joinUse the real people-search routelivenessStop reusing the headed page after its browser closeslivenessStop reusing the headed page after its browser closes, closes #4176merge-tracker--help exits early and post-merge hooks resolve from the code root under an external data rootmerge-trackerA corporate-form merge keeps the row's employer name and prefers an exact company matchmetaPoint CITATION.cff and package.json at career-ops.org, and stop the blurb drifting across five filesollama-evalStream the response and make num_ctx configurable via OLLAMA_NUM_CTXpdfRecognize Chinese section titles in SECTION_ALIASES, closes #3658plugin-installAdd --help and reject unknown flagsprovidersA lone surrogate in one id/slug no longer aborts the whole pageprovidersA lone surrogate in one id/slug no longer aborts the whole pageprovidersApply default headers case-insensitivelyprovidersCoerce before the try; drop tkms encode of the config localeprovidersPin accept-encoding so zstd bodies are not truncatedprovidersPin accept-encoding so zstd bodies are not truncatedprovidersRadancy stops trusting totalResults, cache-busts JSON, retries every fetchprovidersRoute feishu-jobs and mokahr id encoding through _safe-urlrejection-latencyReport placeholder-employer applications instead of dropping them silentlyrheinmetallGuard the slug-fallback decode against a malformed percent-escapescanOpt-in location-aware company+role dedupe, closes #3750scanPrioritize configured locations in Workday facet recovery, closes #3850templatesMake the CV template's second hardcoded color themeable, closes #3695test-allDiscovered-suite guards ignore calls mentioned only in commentstest-allDiscovered-suite guards ignore calls mentioned only in commentstestsGuard subtree-anchored walkers against nested checkoutstestsPass --confirm to apply in the local-paths regression legtestsSkip nested checkouts by marker, not by the name .git, closes #3499tkmsRe-encode the config locale, hoisted out of the row loop to fail loudtoken-trackerAdd MiniMax-M3 and MiniMax-M2.7 ratestrackerCarry the tracker layout through the export round-trip, closes #3703trackerMap "fecha" to the date column, closes #3705trackerResolve addition columns by name so score and status cannot transposetrackerStrip invisible control characters at the cell sanitizer, closes #3892triageWeights sum to 1.00 and a test pins prose against the formula, closes #3738updateResolve preserved files before staging so :(exclude) never reaches --literal-pathspecs, closes #3740url-keyPreserve existing fragment comparison paramsurl-keyPreserve hash-route posting identityurl-keyPreserve hash-route posting identityverify-cv-factsA proposed plan horizon is not a metric claimverify-cv-factsRequire a real word, not a bare capital letter, for a title claim, closes #3907verify-cv-factsStop flagging ordinary prose as tool claims, closes #3639verify-cv-factsTell a disabled fact gate apart from one that ran clean, closes #3894webDetect a real tailored CV/cover on disk, not just the tracker flagwebDon't let a failed fetch become a scored reportwebFence agent CLIs at the spawn boundarywebGive grok a parser, and make the token fold per-CLIwebIdentify the verdict block by its heading, not by the letterwebParseCliJson misses set-status.mjs's pretty-printed successwebResolve the tailored cover for THIS application, not the company's newestworkdayTag a split whose chosen facet under-covers the board
New
discardAdd discard-log analytics and tuning summary, closes #3392ofertaAdd evidence-tiered requirement importance to Block BpluginAdd h1b-sponsor for DOL sponsorship history on US rolesprovidersAdd Built In aggregator providerprovidersAdd Feishu Jobs and MokaHR scanner providersprovidersAdd Garena careers providerscanAdd a durable machine-readable scan receiptscanRemember permanently dead ATS boards, closes #2840templatesCJK support for the LaTeX/Overleaf CV path via tectonic, closes #3553updaterRequire confirmation before installation, closes #2865
Fixed
agent-inboxLock resolve rewrites so a concurrent add is never dropped, closes #3478analyze-patternsStop counting Applied as positivecalibrateResolve the tracker colmap from the line array, not the header line, closes #3495cvBlock delegated authorship escalationcvReject CV payloads whose section keys the builders never read, closes #3523dashboardMatch company slugs at hyphen boundaries so Meta cannot open Metabase's CVdata-rootResolve templates/states.yml from the codebase, not the data rootemailAlign fit points with the tailored CV via the pdf-index row, closes #3460fact-gateCount education and training nouns as metricsfunnel-velocityFold status-log history into calibration rates, closes #3493geminiResolve encoding mojibake on Windows and route localized modesgitignoreThe 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 quadraticallyjd-skill-gapRecognize Traditional and Simplified Chinese requirement headingsmerge-trackerA corporate-suffix variant is the same employer, closes #3665merge-trackerTwo '?' rows with no Via silently merge, overwriting one, closes #3410ofertaLead Block B with the decisive columns and freeze their orderopenai-evalStream the evaluation call instead of a single buffered responseopenrouterWrite scan-history and pipeline through the shared locked writerspdfAccept the canonical modes/pdf.md tailoring order in validateCvSectionOrderpdfRun the fact gate before rendering a CVpluginsA YAML typo in plugins.yml no longer destroys the whole config, closes #3592portalsSweep and validate job_boards, not only tracked_companiesreply-matcherA partial role-word match must be a whole wordreserve-report-numHandle --help/-h explicitlyrole-matcherA level stated on both sides of a title must agreescaffolderRestore the published npm package namescan-ats-fullCollapse a Workday requisition served under several sites of one tenantscan-ats-fullSend the progress counter to stderr under --jsonscanDo not block Dublin OH as IrelandscanResolve scanner user data against the data root, not the cwd, closes #3510set-statusA transition into Applied seeds the follow-up from set-status itself, closes #3459skill-extractRecognize marketing/GTM skills and stop reporting tracked employers as gapstemplatesHonor profile font_family in the Traditional Chinese CV block, closes #3154templatesKeep CJK fallback fonts active for ja, zh-CN and kotestsAnswer gitignore probes that cross a user-layer symlinktestsStop the photo suite writing cv-preview.html into the user's data roottrackerReject malformed application IDs instead of coercing themtrackerResolve templates/states.yml from the module, not the cwd, closes #3508trackerResolve the derived index path at call time, not at importtrackerSort the applications table by # ascending on writetriageFall back to Playwright when WebFetch finds nothingupdate-systemApply() cannot commit when a path it stages is ignored or never trackedupdatePoint the updater at the repository's new homeupdaterBack up self-bootstrap edits before checkoutupdaterScope commits to shipped filesverify-cv-factsBind a count to the nearest metric noun, not the farthestweb,dashboardPoint two user-facing references at the repository's new homewebA company with no usable slug must not match every tailored CVwebEnable apply from the generated pdf indexwebFind Grok in its default install dirs, not only on PATHwebOrder the Today action queue before truncating itwebPreserve a malformed portals.yml instead of overwriting it with the examplewebRank "Awaiting your decision" by every EVALUATED alias, not an English prefixwebRequire the cv- prefix so the tailored-CV resolvers stop returning the cover letterwebResolve the tailored CV for THIS application, not the newest for the companywebSelf-host the production fonts so the app starts without GooglewebTell the beta reporter's user when the dupe search could not runworkdayRecover offset-clamped tenants with a facet splitworkdayResolve a CXS-form URL as the endpoint, not as a careers page
New
application-answersRead the evaluation's Block H draft answerscvAdd "text" output_format — tailored markdown CV, no PDFcvATS-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 continueshired-wallThe audit line speaks to the person mid-searchhired-wallThe badge is the title — self-identifying label, own share line, tighter audit lineportalsProfession-agnostic examples in portals.example.ymlprovidersJobsDB Hong Kong via the existing jobstreet providerwebAdd 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 itcv-sync-checkResolve prompt paths from CODE_ROOT instead of an undefined projectRootcv-sync-checkStop allowFail from excusing an uncaught crashdashboardRead job URLs from the tracker before the legacy enrichment tiersdepsRefresh web lockfile for Next updatedoctorSurvive a null entry in installed_plugins.jsonharnessMake the syntax gate recursive, shared with npm run linthired-shareSuggest outcome.mjs's real syntax in the no-Hired-row errorproviders/icimsFill a missing location from the posting's JSON-LDscanLevel 1 runs Playwright sequentially, matching the shared-session rulescanOpt-in word:/stem: anchoring for content_filter keywordstestsScope the profile pin and move the last hand-registered suitesupdate-systemRefuse to run when the install is not its own git toplevelupdaterParse git status with -z so quoted paths and renames match real filesverify-pipelineRecover a report number from a link target written with backslasheswebHonour language.modes_dir and language.output on web-triggered runswebIgnore nonfatal CLI stderr on clean run exitwebOnly surface follow-ups that are actually duewebRegenerate the nested web/ lockfile on postcss bumpswebShow a cause-specific hint on job failure instead of an always-auth promptwebShow Via attribution for confidential employerswebStop evaluation tables collapsing to one word per linewebStop tracing runtime data pathswebTab label spacing and report table word-breakingwebUse next/link for decision-card report link
New
- Add /calibrate — check evaluation scores against real outcomes
applyRecover previous answers through --read --strict at the CLI seamartifactsATS form copy-paste plain-text exporter- Clean-markers — audit/strip hidden Unicode from generated text outputs
cliAdd help flags to check-livenesscliApplication-artifacts.mjs honours --helpcommunityPR adoption ladder for quiet PRscommunityThe Hired Wall, a verifiable ledger of people hired with career-opscvAdd optional Interests section to the HTML CV templatedoctorDetect personalization files still carrying template contenthired-wallAnonymous cards carry sector · location, mirroring the credited-card hierarchyhired-wallVerified-hires framing, one CTA line, anonymous silhouette, months parsingoutcomeAdd --clean-output to archive-then-remove tailored CVspluginsRegister career-ops-plugin-xquik (X hiring posts via Xquik, BYO-key)providers/getonbrdScan multiple categories per entryprovidersAdd ITviec provider — first Vietnamese job sourceprovidersAdd Torre opportunity-search providerprovidersCareerViet, second Vietnamese job sourcetemplatesAdd ATS-friendly single-column CV template packtemplatesDiscover template packs by nametitle-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 JDbuild-cv-latexRender markdown bold in bullets as \textbfcalibrateRead all 14 outcome spellings outcome.mjs writescliValidate flag values in detect-reposts via the shared safeIntFlagcontactoStop searching for contacts the mode never usescv,pdfAddress CodeRabbit review feedback for #2213datesWeekly-digest and rejection-latency read the local day, not the UTC daydoctorSurface tracked .bak backup files as a warningfact-gateA non-English CV inflating headcount returns 'pass' — say so insteadfollowupStop reporting the candidate's own address as a contact to chasefollowupStop truncating plus-addressed emails at the plusgfi-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 viewBoxhired-wallHonor both permission wordings and default public stories to full crediti18nPreserve safety guardrails in localized modesjobbankcaCount raw entries for paginationmerge-tracker--backfill-urls rebuilds unfillable rows to full header widthoutcomeA tracker edit forks the append-only journal, and directory order decides which half countspdfEnforce workspace boundary in direct rendererpdfRun the CLI when reached through a symlinkpipelineUse browser-first LinkedIn extractionpluginsIsolate cmdRun results to the requested plugin idpluginsScale export hook timeout with tracker sizeportals.exampleDrop retired EchoJobs blockprovidersA16z treats a non-positive total_pages as absent, not as one pageprovidersTotal_pages outranks a short page in the a16z sweep loopreconcile-pipelineValidate CLI flags via the shared helper- Resolve skill paths from project root
salary-gapDecide which separator is the decimal point before deleting eitherscanThree scanners stamp first_seen in UTC, the reader measures it in localstats,calibrateLedger-aware funnel + calibration (#1428, #1724)stats,calibrateReject malformed status ledger rowsstatsStop reporting a neighbouring counter when scan-runs.tsv driftsstory-provenanceMake the context matcher script-aware, not ASCII-onlyupdate-systemNever prune a file the update just preserved, or an asset it referencesupdateDrop the duplicate prune loop that deleted stale files twiceverifyA check that could not run is a failure, not a warningwebClassify a tracker-lock filesystem failure as itself, not as contentionwebKey company logos with the Unicode-aware normalizer so non-Latin names don't collidewebSalvage truncated JSON at each prefix's own depth, not one global padwebStop hiding an employer's whole board after one evaluationwebStop killing evaluate runs at 285s and misreporting the kill
New
anti-fabricationTier the Source-of-Truth boundary and add story-provenance-checkcontactsLinkedin-join.mjs — warm-intro finder from a LinkedIn connections exportcvOptional url support for projects in HTML and LaTeXdetect-repostsSkip multi-employer aggregator boards, and say whypdfDeclare CV section order in config/profile.ymlprovidersAdd jobbankca, Canada's federal Job BankprovidersJob.description for recruitee, ashby, and opt-in smartrecruitersprovidersMycareersfuture, Singapore's national job bankscanAdd Hacker News scanner with optional AI enhancementscanOpt-in anchored keyword matchingverify-pipelineFlag a malformed follow-ups.md instead of reading it as emptywebRestrict the local dashboard API to same-origin and loopback
Fixed
add-entryDelegate flag validation to shared validateFlagsagent-inboxSeed the queue under the lock, not before itashbyStop retrying a permanent failure, and honour a clamped Retry-AfterashbySurface remote work model in the location stringbatchKeep JD word count machine-readable under FORCE_COLORclassify-tierAssociate + an academic rank is not entry-levelcliClose the missing-operand hole for value-taking flagscliValidate browser-extract flags and honour both value formscliValidate fix-slugs flagscvHonor Korean profile font themedatesSeven more today-gates resolve in UTCdepsUpdate web npm dependencies (major)detect-repostsConcurrent openings were reported as repostsfollowup-cadenceValidate CLI flags via the shared helpergreenhousePopulate job.description from the boards API content fieldlivenessA dead third-party host must not poison the whole verdictlivenessAdd a LinkedIn rung so LinkedIn postings get a real verdictlocksOne recovery judgment, imported by all three copieslocksShare the waiting half of the protocol with the three lock copiespdfName both sides when the lexical containment check firespdfName canonicalization failure separately from a real workspace escapepdfStop the batch-evaluate fixture leaking its tracker envpipeline-lockA vanished lock is not a lock you may deletepipeline-lockCarry the judged directory's identity to the rmpluginsDiscover a plugin directory that is symlinked into a plugin rootportals.exampleName the support ROLE, not the whole domainproviders/leverFold categories.allLocations into locationprovidersRetire echojobs, feed is gone behind bot protectionprovidersValidate resolved addresses before connecting (DNS rebinding guard)rename-syncMigrate 5 vulnerable call sites to renameSyncWithRetrysalary-gapTreat a period as thousands grouping, not a decimal pointset-statusResolve --report links from the Notes cell on customized layoutstemplatesExtend profile font_family override to ja and zh blockstemplatesKeep a project's tech line with the description above ittestsAssert flag echo by substring, not by unescaped RegExptestsAssert the flag echo with includes instead of an unescaped RegExptestsGuard the web/ mirror import behind existsSynctestsKeep the end of a failing script's output, not just the headtestsMake the suite symlink-aware for externalized user layersupdateRefuse non-canonical paths in the local declaration fileupdaterParse the SYSTEM_PATHS array instead of scraping it with a regexupdaterSettle same-version SHA mismatch on tree content, not SHAsupdateStop misreading upstream's own content as a local editverify-portalsDecode the HTML entities a board page serves in its titleverify-portalsStop the slug repair path adopting a stranger's boardwebGive the methodology link a real tap target and a new-tab cuewebKeep child stderr out of the status response on the crash pathwebKeep the query string in the Explore dedup key so distinct postings don't collapsewebKeep the run stream alive during silent agent phaseswebReport the uncapped weekly match count while keeping the render boundedwebStamp pipeline first_seen with the local day, not UTC
New
application-answersParse a rendered section back into a snapshotbatchNative Node.js batch evaluator for Geminicompany-historyEmit no-response-friction signal per RFC #1506 schema v1cvMake Work Experience an optional sectiondiscover-atsProbe the long-tail ATS vendors, not just the big threedoctorEmit the Gemini Node 20+ verdict instead of leaving it in prosefollowupsExport withFollowupsLock so other writers can share the lockofertaAI-screening disclosure signal — Block G Signal 15portalsAdd Wellfound search queries to the example templateprovidersAdd yourator job board providerreportsAdd reports_to to the Machine Summary schemascan-ats-fullOptional title_filter_full override for the full-board sweeptitlesLet the mode retire a keyword, not only add one
Fixed
add-entryExact-match dedup keys so a prefix cannot false-positivearchive-postingReject mistyped flags via the shared helperbatch-runnerCurl pre-fetch JD file to avoid empty $jd_file fallbackbatch-runnerEmit the JD word count color-independentlyclassify-tierValidate CLI flags and add a usage blockconsiderPerform GET /jobs CSRF handshake before the POSTcontactsAdd -h/--help and reject unrecognized flagscover-letterPreserve --out subdirectories inside the output rootcvAn empty Skills section no longer deletes the sections after itfunnel-velocityValidate CLI flags via the shared helperintakeTreat a nonzero version probe as present, not missinglivenessRead same-origin iframes so embedded postings aren't false negativeslocksThe other two copies of the protocol had the same Windows bugmerge-trackerDon't let an unscoreable (N/A) re-eval overwrite a real scoremerge-trackerWrite rows at the header's actual width on customized trackerspipeline-lockAn unreadable owner stamp is not an ownerless lockpipeline-lockTime out a wedged holder, not an unlucky waiterpipelineSerialize browser-backed extraction so workers never share a sessionportalsBlock German student and support postings in the example title filterportalsRefresh example board URLs after ATS migrationsprovidersRaise inter-page pacing to 250 ms on the eight providers still at 150providersSenjob was the fifth private entity decoder, and the weakest — it emitted C0 controlsscanAdd block_hard tier so always_allow cannot discard an explicit blockset-statusRejects today's date east of UTC, logs tomorrow's west of itstatsValidate CLI flags via the shared helpertest-allTolerate Windows EPERM on fixture cleanup so a green run stays greentrackerTreat Windows rename contention as contention, not deathtrust-validatorA company with an accent in its name is flagged for being on its own domainupdaterDetect tree drift and prune retired system files (#2630, #2532)updaterParse git status paths from untrimmed outputupskillValidate CLI flags via the shared helperverify-cv-factsCatch fabricated headcounts outside softwareverify-portals--add probes slugs that cannot exist for an accented company namewebBlock_hard survives the Explore round-trip — type, URL params, seed and serializerwebPersist the only installed CLI so jobs can startwebResolve 27 unmapped states.yml aliases and fix the Turkish status foldwebResolve company logos by name, not one guessed domainwebSafe Codex AI-search exec with mtime-keyed capability cachewebStop first-run from claiming no setupwebTake the core followups lock so web writes cannot race the seederwebToday primary action opens the reportworkspaceKeep artifacts and PDF metadata in the tracker's workspace
New
cliAdd --help / -h usage block to stats.mjscliShared flag-validation helper, migrate 3 fixed scripts, fix scan.mjs, closes #2775dashboardAdd a POSTED column showing requisition agedashboardAdd Stats analytics view with score quality & seniority mix chartsintakeRead documents/ locally to propose source-annotated profile additionsinvite-matchDistinguish AI-interviewer platforms from human calls, closes #2673negotiationROI-based salary-negotiation talking points from verified achievementspdfBatch render path reusing one Chromium across N CVsprovidersEightfold AI talent-acquisition boardsprovidersExtend getro with auto-resolve, salary, retry and remote-detect, closes #2602providersSenjob — the scanner's first African source, SenegalrankOpt-in LLM relevance re-ranker for pipeline.mdscanAND-groups in title_filter.positivescanRecord failed runs in scan-runs.tsv so trends exclude survivorship biasskill-extractRecognize certifications, not just engineering toolstemplatesFive named CV templates + a contract test for template variantstracker-sync-checkFlag applications.md rows that active-interviews.md has already moved pastupdateDeclare fork-local paths outside the system layerupdateRestore locally deleted system files instead of preserving the deletionwebGive the Apply page a way back and a way to record that you applied
Fixed
add-entryKey non-Latin headings and dedup keys faithfullyadd-entryReject mistyped flags instead of reading them as dataagent-inboxGive concurrent add() a burst-sized lock timeout, closes #2824agent-inboxSerialize concurrent adds through the shared lockagent-inboxStop dropping requests queued during an addarchiveKey JD captures to report numbers so they resolve after capture dayassessment-logReject unknown flagsbatch-tailor--min-score 4.5 was silently ignored, and the worker's pdf mode path was cwd-relativebatchRetry state updates and lock reservations to prevent worker silent dropsbuild-cv-htmlRender numeric year/date scalars instead of dropping thembuild-cv-latexNumeric year/date scalars are still dropped — #2641 fixed only the HTML mirrorcheck-table-freshnessValidate CLI flags and add a usage block, closes #2855ciOnly greet a first-time contributor when it is actually their firstciSkip the upgrade leg when nothing managed changed, instead of failingclassify-tierAn incidental senior word outranked an explicit intern markercliA one-letter typo returned a false all-clear at exit 0 in 4 reporting CLIscompany-historyRecord response dates via --on, not --note free textcontactoLinkedIn connection-request limit is 200 on free tier, not 300csodReplay bootstrap session cookies and repair fetchResponse()cv-factsTreat a k/M/B magnitude suffix as part of the numbercvKorean and Traditional Chinese CVs had no font rulededup-trackerReject unrecognized flags instead of silently live-runningdepsMake js-yaml imports work on both 4.x and 5.xdepsPatch 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 itdoctorDetect Playwright MCP servers provided by Claude Code pluginsdoctorValidate CLI flags and add a usage block, closes #2856evalMerge openrouter tracker TSVs and send Ollama options to the native /api/chatfindPrint the one USAGE constant on the empty-query path toofindReject mistyped flags instead of searching for themfollowup-cadenceParse annotated pins, and add a retire directivefollowup-seedResolve "today" in local time, not UTCfollowupIgnore an apply date cited about another row, closes #2607invite-matchValidate CLI flags and add usagejd-similarityAdd --help and reject unknown flags instead of reading them as paths, closes #2772jd-similarityThe seniority gate fired on JD boilerplatejd-skill-gapRecognize all six markdown heading levelsjd-skill-gapRecognize sentence-form requirement headingsjobviteMigrate to the public XML feed after the JSON API retirementkeysStop the dotted-I fix from collapsing Polish, Lithuanian and MaltesekeysStop the Turkish dotted capital from splitting one employer in twolivenessClassify a rate-limited posting as uncertain, not expiredlivenessTreat an api.lever.co 404 as inconclusive, not proof of removallocksTreat Windows rm/stat contention as contention, not deathmatch-starScore a non-English story bank against a question in its own languagemerge-trackerDeterministic dedup on the posting URLmerge-trackerMatch inline URL headers so URL dedup activates for doc-style rowsmerge-trackerRe-eval no longer inherits the superseded report's checkmarkollamaInclude profile context in evaluationsoraclecloudAccept Oracle's numbered tenant apexes (oraclecloud1-99.com)patternsRate denominators counted rows that could never contributepipeline-lockA non-EEXIST mkdir refusal is contention, not a fatal error, closes #2777pipeline-lockJitter the retry so a starved writer costs a retry, not an itemplugin-auditValidate CLI arguments and add a usage block, closes #2771process-qualityThree undisclosed employers were reported as disclosedprovidersDecode HTML entities in titles before matching so encoded ampersands stop dropping jobsprovidersFill in the docs and vendor-detection gapsprovidersHarden workable with retry, headers, and serializationprovidersIsRetryableError no longer misclassifies a refused redirectprovidersMake themuse resilient to per-page fetch failuresprovidersPersonio falls back to HTML scrape when the XML feed is disabledprovidersPhenom pagination/retry fixes, drop dead auto-detectionprovidersReject numeric entities outside the XML 1.0 Char setprovidersRoute seven RSS decoders through the shared safe entity decoder, closes #2790providersRoute softgarden and radancy through the shared entity decoderreply-matcherRequire corroboration for partial role-title matchesreply-matcherThe '?' unknown-employer placeholder matched everythingreply-watchReject unrecognized CLI flags instead of treating them as a pathreserve-report-numDo not read a bare date file as a report number, closes #2757role-matcherTokenize non-Latin role titles and scope the mark fold, closes #2781scan-ats-fullCap single-host ATS sweeps at their own concurrencyscanLocate the URL anywhere in a pipeline.md entryscanTake the shared lock for scan-history.tsv appendsset-statusStop the --role guard from folding every non-Latin title to the same keystatesAliases the engine accepts were missing from states.ymlstatusFold Turkish dotted capitals so uppercase tracker rows resolve to canonical statestestsContain a discovered suite that throws at importtheme-styleA `$`-pattern in a profile style value splices the body into the CV'supdateCommit the index so file-mode changes are not droppedupdateIgnore CRLF/LF-only differences when detecting local system edits, closes #2817updateReconcile .gitignore on apply so new ignore rules reach existing installsvelocityCount a web-written transition as an observationverify-cv-factsFold allow_metrics through the same noun synonymsverify-cv-factsTreat a period as a thousands separator toovoice-dnaMake voice-dna.md private via the template patternwebAdd Grok Build CLI to the web runtime pickerwebAnalytics 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 runwebCarry the posted: segment so web evaluations reach the POSTED columnwebDetect OpenCode in its default install directorywebEmit the posting URL in the tracker-additions TSV so web runs join the dedupwebEnforce that no runtime grants itself blanket write permissionwebFinish Unicode company keys for explore + registrywebFold Turkish dotted capitals in status keys, and stop hand-copying the state listwebKeep Codex JSONL + exit code authoritative for web scoringwebLet the pipeline table scroll horizontally instead of clipping on narrow screenswebMake the tracker reader agree with parseTrackerRow on row shapewebPrevent Codex run jobs from waiting on stdinwebRead target_roles with the shape it is actually written inwebShow the retry card, not the update-checkout panel, for runtime scan errorswebSkip {n}-RESERVED.md sentinels when looking up reportswebStop the 16-chip cap from truncating the user's own portals.ymlwebStrip the author letter from any lettered block, not just A-GwebTake the core tracker lock in POST /api/statusworkdayKey the cap-hit warning on entry provenance, not on --since
Faster
analyticsDrop redundant existsSync probes before report readsscanRead 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.xdepsPatch 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 itkeysStop the dotted-I fix from collapsing Polish, Lithuanian and MaltesekeysStop the Turkish dotted capital from splitting one employer in twoscanTake the shared lock for scan-history.tsv appendswebAdd Grok Build CLI to the web runtime pickerwebAnalytics 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 runwebCarry the posted: segment so web evaluations reach the POSTED columnwebDetect OpenCode in its default install directorywebEmit the posting URL in the tracker-additions TSV so web runs join the dedupwebEnforce that no runtime grants itself blanket write permissionwebFinish Unicode company keys for explore + registrywebFold Turkish dotted capitals in status keys, and stop hand-copying the state listwebKeep Codex JSONL + exit code authoritative for web scoringwebLet the pipeline table scroll horizontally instead of clipping on narrow screenswebMake the tracker reader agree with parseTrackerRow on row shapewebPrevent Codex run jobs from waiting on stdinwebRead target_roles with the shape it is actually written inwebShow the retry card, not the update-checkout panel, for runtime scan errorswebSkip {n}-RESERVED.md sentinels when looking up reportswebStop the 16-chip cap from truncating the user's own portals.ymlwebStrip the author letter from any lettered block, not just A-GwebTake the core tracker lock in POST /api/status
New
coverOptional letter.signature sign-off block, closes #2510cvStrip the Core Competencies section when it has no entries, closes #2509doctorWarn when an API key is overriding the Claude subscriptionfollowupRejection-latency signal, courtesy-threshold onlyinvite-matchRecognize rejection emails, not just interview invitesofertaMinimum-wage lawyer question, arithmetic-onlyofertaPay-transparency range-width check, self-computed onlyoffer-prepSub-statutory terms route to lawyer, no floors tableprovidersAdd join.com SSR __NEXT_DATA__ parserprovidersAdd remotli — Swiss remote job boardscanAdd getro, consider and joinup zero-auth providersscanMake the pipeline and scan-history paths env-overridable, closes #2271
Fixed
a16z-speedrunRetry a transient page failure instead of aborting the whole boardarbeitsagenturMove to the v6 Jobsuche APIcoverFail on an unresolved template token instead of shipping it into the lettercvDrop empty Skills section instead of rendering a bare headercvPair _EMPTY fallbacks with their block so mixed rows stay alignedcvPass a replacer function so $-patterns in candidate text stay literaldedupUse the shared Unicode-aware company key instead of a local ASCII copydedupWrite the blind-via key prefix as an escape, not a raw NUL bytedoctorTreat 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 moduleinvite-matchNon-Latin company names returned zero candidatesjd-skill-gapCRLF-terminated JDs extracted zero skillsmerge-trackerWrite a lower-scored re-evaluation through instead of discarding itprovidersHackernews thread lookup filters by the whoishiring tagprovidersMove The Hub to the v2 jobsandfeatured APIprovidersResize a16z page budgets for the 50-job page sizerepoAdd .gitattributes so Windows checkouts stop producing whole-file diffsscanRead --company/--posted-after/--posted-before in =value form tooscanUnicode-aware keys for role dedup and company matchingseedsWalk every YC page instead of stopping after page 1, closes #2525seedsWalk every YC page instead of stopping after page 1update-systemApply .gitattributes before the files it governswebDerive company matching keys from the core, not an ASCII-only copywebRe-read states.yml when it changes instead of caching it for the process lifetimewebRoute Today's "See all N" link to the fresh-matches viewwebTake Write/Edit away from the dashboard's pdf mode
New
- Add company:funded — review-first funded-company discovery from public RSS sources
cvAdd optional Awards / Honors section to HTML + LaTeX CV templatesi18nAdd Italian translations for interview modespdfOpt-in hiring-manager audit pass — adversarial, research-grounded CV reviewprovidersGetManfred board-wide feed (Spanish/EU tech, salaries published)repostsAdd --help usage block to detect-repostsscanAdd --since, a relative posted-date bound that also stops paging earlytestDynamic upgrade PR gate — old install applies the commit under testwebFollow-up Tracker page with logging, history, and cadence settingsweekly-digestWeekly interview digest aggregator
Fixed
batch-runnerTab-IFS collapse recorded score "-" for every successful offercli--flag=value was silently ignored in five scriptscompany-fundedCatch the layoff spellings #2404 left throughcompany-fundedThe cuts N% layoff exclusion never matchedcompany-historyCount a hire as a company responsecv-factsThe anti-fabrication gate saw nothing in five shipped localescv-factsThe employer/title gate only matched lowercase triggerscv-latexSingle mailto: scheme + escape OT1-unsafe glyphsdashboardLocalize the hired status label and buffer split stream openersdashboardThe progress funnel dropped Hired from every stagededupUse Unicode-aware Via key for blind-employer groupingdepsUpdate npm dependencies (+ Dockerfile playwright pins, web lockfile sync)doctorDetect Playwright MCP in JSONC OpenCode configsfingerprintNon-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 summarylivenessClassify transient 5xx as uncertain, not expiredmerge-trackerCollapse placeholder Notes to the re-eval markermerge-trackerFour silent data-loss paths in the merge loop, with Unicode-safe company matchingprovidersA16z speedrun feed silently truncates to 50 jobsprovidersDead 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 runscan-ats-fullKeep the checkpoint when a resolver outage stops a sweepset-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 optionstailorPrompt-cache the openai-tailor.mjs static system prefixtest-allThe states.yml freeze guarded 6 of 9 idstestForbid finish() in discovered suites — it forges the global verdicttestReport the Windows-unobservable lock contention signal instead of failingtestsBudget harness waits for slow runners and preserve crashed-script diagnosticstestsFind Git Bash under Scoop and name the fallback shell in failurestestsIsolate tracker-columns fixtures from the real reports/ directorytestStop test-all silently passing when a node:test suite failstestUse a junction on Windows for the node_modules linktrackerNon-Latin company names all keyed to empty string, silently overwriting each othertrackerRank Hired in dedup, canonicalize its aliases, stop bare tracker-number merges across rolesverify-cv-factsStop the modifier count from deciding whether a claim existsverify-pipelineOrphan check masks and invents orphansverify-pipelineUnicode-aware keys for company/role/Via groupingwebRender PDFs from the backend instead of the spawned agentweekly-digest--from=… was silently ignored, digesting the wrong weekworkableUse the public widget API so large accounts are scanned
Faster
detect-repostsBucket titles instead of comparing every pairfingerprintPopcount table + hoisted loop state in findCrossListingstestsFix the dead SSRF DNS stub and cut three fixed costs from test-all
New
complianceCheck-table-freshness.mjs — staleness validator for jurisdiction tables (closes #2036)contactsCompany-history.mjs, employer silence and repost facts, closes #1711contactsJob-search phonebook with vCard exportcvBlock unsupported employer, title, and tool claims in cover letterscvRecommend CV reuse for similar JDs — deterministic jd-similarity helperdoctorCLI-aware Playwright MCP detection + OpenCode config supportinterview-prepDetect call platform (phone/Zoom/Teams/Meet) from invite textinterview-redflagProtected-grounds question detection with jurisdiction tableinterview/debriefCorrect contradicted facts in the prep file in placeinterview/planWire in interview-prep's sourced-question research before Block 4interviewDebrief directly from an existing transcriptledgerSet-status transition log + mode wiringoferta/applyImmigration-status requirement overreach — jurisdiction table + posting signal + form warningoferta/applyJurisdiction-prohibited content signal — table + Block G + apply-form warningofertaAgency licensing check — jurisdiction table + registry pointer for agency-mediated postings (closes #2037)offer-prepJurisdiction-aware restrictive-covenant notesoutcomeOutcome recording and application archiving, phase 1portalsStandalone fix-slugs.mjs — auto-write ATS slug fixes to portals.ymlprovidersA16z speedrun talent network board-wide feedprovidersAdd iCIMS to the reverse-ATS full sweep, closes #2137providersCryptocurrencyjobs — Web3 job board via public RSS, zero-authradancySupport legacy TalentBrew markup and the JSON results fragmentscan-historyAdditive normalized-company column for reliable repost keyingscanAdd Playwright scanner for Interamt.descanCountry-eligibility filter for remote postings, closes #2093scanNegative-cache resolver refusals and stop the sweep on a resolver outagescanPace DNS lookups so a full sweep can't trip a resolver's rate limitstatsWire followup-cadence's cold classification into activeAppstestSeed-fixture.mjs + era-appropriate install fixturestriageStandalone 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 gapsbatchDon't mark a worker-reported failure as completedciA fork signature's valid check must not go red when the ack comment can't postcoverPrevent double comma in achievement bulletsdashboardPin the row's own status to the top of the status pickerdashboardStop reading funding and valuation figures as PaydashboardThe 'hired' status renders with no colour in the pipeline listechojobsKeep hybrid roles distinguishable from remotefollowup-seedAge out an orphaned recover guard so it can't permanently disable stale-lock recoveryfollowupAccept an estimated apply date and report which date the age came fromfollowupRecognise name-only outreach so an empty contact list means no contactjd-skill-gapCanonicalize CV and JD tokens through skill-extractmerge-trackerStop sibling-req clobber when the qualifier is a slashed acronympipeline-lockFloor the ownerless stale check, harden the timeout testsrole-matcherFold accented Latin letters before tokenizing role titles, closes #2207scaffolderMaterialize the Kimi skill entrypoint on symlink-less filesystemsscanA title-stated remote role survives a city-only locationscanIgnore StepStone's volatile rltr param when deduping posting URLsscanPortal-health cross-process lock + resolve PORTAL_HEALTH_PATH from cwdscanRecord auth, server and unknown fetch errors in portal-health instead of reachabletestAccept a materialized skill entrypoint, not just a symlinktracker-utils, followup-seedFloor the ownerless stale-lock check so a just-created lock can't be stolentrackerA data row containing --- is invisible to merge-tracker dedupwebAdd Hired to the states.ts FALLBACK so the degraded path accepts itwebLabel-aware pipeline.md reader — posted:/trust:/note: never misread as columnswebPropagate the Hired terminal-success state across the whole dashboard
New
batchAdd batch-tailor.mjs for bulk CV tailoring of high-scoring roles, closes #1836cliAdd Cursor as a supported CLI hostcvSupport declarative section HTML partials from disk, closes #2183dashboardAdd a RESPONDED filter tab to the pipeline screen, closes #1999dashboardBuild the pay-span regex from an explicit currency listevalToken-budget-aware context compression for the Gemini and OpenAI evaluators, closes #2077i18nAdd Dutch (nl) modeslatex-texSupport resumeItemWithoutTitle bullets and resumeSubItem skillsofertaFlag explicit no-sponsorship as a hard blocker, closes #2016pdfDynamic CSS theming from a profile.yml style block, closes #1837providersAdd Flowxtra board-wide job providerprovidersAdd VDAB zero-auth providerscanDiscover-ats.mjs — resolve a company list to scannable ATS boards, closes #1864skillsExtract the shared skill tokenizer into skill-extract.mjsupskillLearning plan on the aggregate gap heatmap, closes #1740
Fixed
agentic-jobsReplace the broken HTML scraper with the documented REST API, closes #2143agentsCompress AGENTS.md ~20% with zero semantic lossbatchUpdate Claude tier mapping to the current model lineupcvAdd GitHub contact link to the HTML CV pipelinedashboardPersist status changes from viewer Discard/SKIP and stale rowsdedupMerge notes from removed entries instead of dropping them, closes #1833depsUpdate dependency next to v16.2.11 [security]depsUpdate module golang.org/x/sys to v0.47.0doctorTreat missing user prerequisites as non-fatal setup warningsfunnel-velocityCount non-canonical Applied rows in the waiting backlogjd-skill-gapRecognize real-world requirement headers, stop at benefitslivenessNormalize typographic punctuation and accents before matching, closes #2162livenessTreat the SPA "has been filled" phrasing as expired, closes #2211match-starTokenize tag matches so short tokens do not substring-collidenormalize-statusesUse header-mapped columns instead of fixed indicesopencodeAdd missing /career-ops command router, closes #2191patternsRecognize the canonical Hired status in analyze-patternspdfApply the CV section-order check to non-English CVspipelineLock appendToPipeline() against concurrent read-modify-write, closes #2188pluginMirror plugin.json at .github/plugin/ for the awesome-copilot validatorprovidersGuard decodeEntities against out-of-range code pointsreply-matcherDecide rejections before offers to stop mis-typingreply-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 titlerole-matcherStrip the "Member of Technical Staff" prefix before tokenizing, closes #1965role-matcherTreat 'product' as a baseline token so PM sibling specialties stay distinctsalary-gapParse US ranges with the currency symbol on both bounds, closes #2190scanKeep body consumption inside the fetch timeout window, closes #2136scanLowercase the path in normalizeUrlForDedup to catch cross-source duplicatesscanRecover Greenhouse office cities when location.name is a work modelscanWord-boundary location keywords + URL location fallbackset-statusFail closed when a lone company row contradicts --role, closes #2009skillRouting drift + discoverable metadata across the agent surfacesuccessfactorsPreserve 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 CItrackerSet SQLite busy_timeout to avoid SQLITE_BUSY under concurrent access, closes #1957trackerSync the PDF column from data/pdf-index.tsv, closes #1429update-systemRollback removes additions left behind under a directory pathspec, closes #2015update-systemVerify the target manifest materialized instead of reporting success, closes #1998verify-cv-factsDetect metric claims the pattern was silently missingwebResolve nested postcss and sharp advisories via overrides
Faster
scanCache DNS lookups in-process to stop resolver floods, closes #2154
New
cvChinese minimal CV templatecvImprove profile-photo configuration and previewexpandAdd /expand mode to discover missing CV competencies, closes #1521gemini-evalStatic prefix as systemInstruction for implicit cachingi18nSimplified Chinese interview modes (plan/practice/debrief)ofertaBlock G signal 9 — third-party platform location tag mismatchopenai-evalHost-gated prompt-cache breakpoint for the static prefixpdfFirst-class zh-CN typography supportpdfWarn on rendered page overflow, --strict-pages opt-in hard limitpipelinePer-step token breakdown at end of runprovidersAdd Alibaba Group careers providerprovidersAdd Gem scanner providerprovidersAdd Jobvite zero-auth providerprovidersAdd Welcome to the Jungle and Agentic Engineering Jobs providersscan--posted-after/--posted-before absolute posting-date filtersscanAdd 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 itpdfDrop empty Education section instead of rendering a bare headerpdfHarden optional-section boundaries, extract shared cv-sections-corepipelineRecognize #1799 score sentinels in verify-pipelineprovidersBuild public SmartRecruiters URLs without /postings/scan-ats-fullWire content_filter into reverse scansscanHide unconfigured salary/content filter summariesscanNormalize cosmetic URL variants for dedupscanSeed 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-suitetrackerRecognize the Hired canonical status in merge-tracker and statsverify-cv-factsStop a bare '<' from swallowing source evidence
New
applyWarn before reapplying to a repeat company, closes #1920cover-letterSupport --format and --report CLI arguments, closes #1828dashboardManifesto shortcut, help entry and footer linkemailAdd confirmed-time no-show follow-up variant, closes #1859interview-prepCross-reference coffee chat notes against interview intel, closes #1940interview-redflagFlag scope/compensation mismatch as a separate fifth dimension, closes #1942interview-redflagSuggest a ready-to-copy blacklist row at Reconsider level, closes #1854interview/planWire the existing Panel Intel table into multi-panelist rounds, closes #1857ledgerImmutable n: ordinal per signature + first-contribution question for new signerslivenessAdd Workday to the zero-token ATS liveness API rungofertaBlock G signal for benefits terminology country mismatch, closes #1935onboardingRoute to the manifesto from the README and the first successful scanpdfAdd role name to the tailored PDF filename for multi-role trackingprovidersAdd Oracle Recruiting Cloud zero-auth providerreportsUnified Risk Summary block joining the five company-risk signals, closes #1737salary-gapTrack compensation figures stated per interview round, closes #1852scanPersist and surface the scanner trust signal to pipeline and history, closes #1743scanTrack portal health over time and surface coverage decay, closes #1744
Fixed
cv-templateKeep role header with its bullets when a location line is presentdoctorWarn when Node is below 22.5 instead of passing silently, closes #1829envrcOnly load the Nix flake when Nix is installedinterview-redflagDrop GitHub PR references from candidate-facing output templatesledger-botMake the first-contribution confirmation copy match what shipsledger-botRestore the 'done' confirmation now that the certificate render is liveonboardingRelay the manifesto note in agent-mediated updatespdfDrop empty Projects section instead of rendering a bare headerrole-matcherKeep base titles distinct from specialized-suffix siblings, closes #1881scan-ats-fullRespect data/blacklist.md, closes #1911scanQuiet 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 #1844upskillKeep fetched JD text as a string in the targeted --url-text path, closes #1894
New
onboardingSurface the CareerOps Manifesto after updates and setup
Fixed
upskillCorrect inverted known-skill suppression in targeted mode
New
batchApply compensation reliability checks to batch workersbrowser-extractConfigurable jd-mode text cap via --max-charscalibrationFunnel-velocity.mjs — own funnel vs market benchmarks (#1693, part 1)cvFact validator — block invented metrics in generated CVsdashboardAdd Spanish (es) locale to the i18n catalog, closes #1764dashboardDiscard reason picker with learning loop, closes #1380dashboardI18n extraction for the Go TUI (split from #1666)emailATS-broken fallback scenario — recover a stuck applicationi18nAdd Traditional Chinese (zh-TW) modesi18nChinese salary reliability checks — zh mirror of the compensation tiersimg-to-pdfConvert a screenshot into a PDF for ATS uploadsinterview-prepURL entry path for a role that was never evaluated, closes #1816invite-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 pathsofertaBlock G signal 7 — AI-buzzword vs infrastructure mismatchofertaCompany-type + compensation-reliability tiers in evaluationsopenrouterPrompt-cache the static system prefix via cache_controlpdfDeterministic HTML CV renderer to cut PDF-step token burnpdfJD skill-gap checker before CV generation, zero-LLM, closes #1558pipelineOpenai-tailor.mjs — headless CV tailoring for the no-agent pathproviders4dayweek auto-detect with spoof-safe host matching (#1657 follow-up)providersAdd LaraJobs zero-auth RSS providerprovidersAdd Meituan careers providerprovidersAdd Tencent careers zero-auth providerregistryRegister serper and theirstack provider plugins (#1645, #1697)registrySplit plugins-registry.json into per-plugin filesreply-watchPaste-reply.mjs manual input path for users without Gmail, closes #1802scanData/blacklist.md — user-owned do-not-apply listscanOpt-in max_posting_age_days freshness gatescanPersist provider postedAt to pipeline and scan-historyscanSuppress duplicate roles via company aliases- Spend_tier config for model-agnostic model routing + batch pre-screen gate
templatesConfig-selectable CV and cover-letter templatestrackerAssessment-log.mjs — skills-assessment events with staleness signaltrackerRecognize "—"/"-" as valid score-cell N/A sentinels, closes #1799upskillAggregate 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 filecoverResolve 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 parsingpdfClean temporary HTML when browser launch failspdfRender markdown bold in CV summary as (ATS-safe)portalsValidator accepts provider-plugin ids like the runtime doesprovidersSupport explicit api: override for ashby/lever with host-pinned guardsreserve-report-numSupport report numbers past 999scanRestore browser-like headers on Workday CXS requests, closes #1811templatesAllowlist the template format to prevent path traversaltestNormalize CRLF at read time for doc assertionstestsClose CodeQL command-injection findings in the test harnesstestsSkip web-reader tests when web/ is absent on core-only installstrackerDetect and prevent duplicate tracker # numbersupdate-systemAdd .claude/hooks/ to USER_PATHSupdate-systemKeep the updater self-loading to survive old→new re-exec