career-ops-v1.27.0

career-ops-hq/career-opscareer-ops-v1.27.0Aug 18, 2026by github-actions[bot]

AI Summary

Adds a Stats analytics view with charts, new providers (Eightfold AI, Senjob), and ROI-based salary negotiation talking points.

Key Highlights

  • Added Stats analytics view with score quality and seniority mix charts.
  • Added Eightfold AI talent-acquisition boards.
  • Added Senjob, the scanner's first African source.
  • Added ROI-based salary-negotiation talking points.

New Features

  • Stats analytics view.
  • Eightfold AI providers.
  • Senjob provider.
  • Negotiation talking points from verified achievements.
  • Batch render path reusing Chromium across multiple CVs.

Full Release Notes

## [1.27.0](https://github.com/santifer/career-ops/compare/career-ops-v1.26.0...career-ops-v1.27.0) (2026-08-18)


### Features

* **cli:** add --help / -h usage block to stats.mjs ([#2556](https://github.com/santifer/career-ops/issues/2556)) ([3d8b53d](https://github.com/santifer/career-ops/commit/3d8b53dcf41917d889deff8435e869a5a53c6550))
* **cli:** shared flag-validation helper, migrate 3 fixed scripts, fix scan.mjs ([#2778](https://github.com/santifer/career-ops/issues/2778)) ([f05fc0f](https://github.com/santifer/career-ops/commit/f05fc0fe8013a28468f0cab69adb281a36c8d37b)), closes [#2775](https://github.com/santifer/career-ops/issues/2775)
* **dashboard:** add a POSTED column showing requisition age ([#2692](https://github.com/santifer/career-ops/issues/2692)) ([a229727](https://github.com/santifer/career-ops/commit/a22972772f2bba7334334550b5eca630d3f26d51))
* **dashboard:** add Stats analytics view with score quality & seniority mix charts ([#2960](https://github.com/santifer/career-ops/issues/2960)) ([9f0c3c3](https://github.com/santifer/career-ops/commit/9f0c3c39f203e29fb742749aef642e122ff8f822))
* **intake:** read documents/ locally to propose source-annotated profile additions ([87abc32](https://github.com/santifer/career-ops/commit/87abc322ab5686cd6c4fd7d91aa3154258d77dcd))
* **invite-match:** distinguish AI-interviewer platforms from human calls ([#2676](https://github.com/santifer/career-ops/issues/2676)) ([7fa3b1d](https://github.com/santifer/career-ops/commit/7fa3b1d2f362f65a3d346a09fd7ba609fffe3eb7)), closes [#2673](https://github.com/santifer/career-ops/issues/2673)
* **negotiation:** ROI-based salary-negotiation talking points from verified achievements ([#2950](https://github.com/santifer/career-ops/issues/2950)) ([03b440f](https://github.com/santifer/career-ops/commit/03b440f15104f1d7545fb8a0b316038f563ba2f0))
* **pdf:** batch render path reusing one Chromium across N CVs ([#2747](https://github.com/santifer/career-ops/issues/2747)) ([7bb5c32](https://github.com/santifer/career-ops/commit/7bb5c3279baad31a4215988576d0a6e99350e774))
* **providers:** Eightfold AI talent-acquisition boards ([#2684](https://github.com/santifer/career-ops/issues/2684)) ([e991d58](https://github.com/santifer/career-ops/commit/e991d5853fdf708639721124c9bac17ff291f2b0))
* **providers:** extend getro with auto-resolve, salary, retry and remote-detect ([#2640](https://github.com/santifer/career-ops/issues/2640)) ([85c0928](https://github.com/santifer/career-ops/commit/85c0928871be11df54c4769a73a5069bbef6b152)), closes [#2602](https://github.com/santifer/career-ops/issues/2602)
* **providers:** senjob — the scanner's first African source, Senegal ([#2962](https://github.com/santifer/career-ops/issues/2962)) ([db9bd6a](https://github.com/santifer/career-ops/commit/db9bd6aefb45c8297184eaa38cd1c1f006cd7ed8))
* **rank:** opt-in LLM relevance re-ranker for pipeline.md ([#2579](https://github.com/santifer/career-ops/issues/2579)) ([03fc92b](https://github.com/santifer/career-ops/commit/03fc92bb04e1fc8821ff4ec71b26bcc6f0da1182))
* **scan:** AND-groups in title_filter.positive ([#2552](https://github.com/santifer/career-ops/issues/2552)) ([5483083](https://github.com/santifer/career-ops/commit/548308354899de91be27fa2df8fefd176ef88e01))
* **scan:** record failed runs in scan-runs.tsv so trends exclude survivorship bias ([713a6b0](https://github.com/santifer/career-ops/commit/713a6b0c928be43ed2fc1201d3cf140457f8c6cf))
* **skill-extract:** recognize certifications, not just engineering tools ([#2603](https://github.com/santifer/career-ops/issues/2603)) ([4c6a1d2](https://github.com/santifer/career-ops/commit/4c6a1d254d9933c0fd0ff3c200b900f7c928547a))
* **templates:** five named CV templates + a contract test for template variants ([#2954](https://github.com/santifer/career-ops/issues/2954)) ([314cbb5](https://github.com/santifer/career-ops/commit/314cbb5f00a5e5e8a5bbcf875948e9f4c9cb8915))
* **tracker-sync-check:** flag applications.md rows that active-interviews.md has already moved past ([a1304a4](https://github.com/santifer/career-ops/commit/a1304a42181ed6a735b2bfcc19db938134061ed3))
* **update:** declare fork-local paths outside the system layer ([#2793](https://github.com/santifer/career-ops/issues/2793)) ([b082ec6](https://github.com/santifer/career-ops/commit/b082ec6a9c4765cebf51d1038ab9a2195caeb434))
* **update:** restore locally deleted system files instead of preserving the deletion ([#2448](https://github.com/santifer/career-ops/issues/2448)) ([bfcaaba](https://github.com/santifer/career-ops/commit/bfcaaba7ba5662cd815b4e573757e9920515e7af))
* **web:** give the Apply page a way back and a way to record that you applied ([#2735](https://github.com/santifer/career-ops/issues/2735)) ([05cc972](https://github.com/santifer/career-ops/commit/05cc972c2d45471ba45a8457c83f488915fc4fa6))


### Bug Fixes

* **add-entry:** key non-Latin headings and dedup keys faithfully ([#2850](https://github.com/santifer/career-ops/issues/2850)) ([27757e4](https://github.com/santifer/career-ops/commit/27757e4896e5213a69440ecf17e54e0a413cbe06))
* **add-entry:** reject mistyped flags instead of reading them as data ([f4c4fda](https://github.com/santifer/career-ops/commit/f4c4fda5b3b31ee78070ea3884d1bc4b0570fc7f))
* **agent-inbox:** give concurrent add() a burst-sized lock timeout ([#2825](https://github.com/santifer/career-ops/issues/2825)) ([513f07a](https://github.com/santifer/career-ops/commit/513f07a2582c7e6dc03644733e796f4aec749f21)), closes [#2824](https://github.com/santifer/career-ops/issues/2824)
* **agent-inbox:** serialize concurrent adds through the shared lock ([#2777](https://github.com/santifer/career-ops/issues/2777)) ([a7f65b6](https://github.com/santifer/career-ops/commit/a7f65b6a63e90560270c4afb213204bab57981ab))
* **agent-inbox:** stop dropping requests queued during an add ([#2614](https://github.com/santifer/career-ops/issues/2614)) ([ad382c0](https://github.com/santifer/career-ops/commit/ad382c0b7f1fc2d4fc9a32094a49931c114e2a4b))
* **archive:** key JD captures to report numbers so they resolve after capture day ([#2701](https://github.com/santifer/career-ops/issues/2701)) ([81d7b06](https://github.com/santifer/career-ops/commit/81d7b069a8a726468d9ca76ebb2d9e768b470f01))
* **assessment-log:** reject unknown flags ([#2802](https://github.com/santifer/career-ops/issues/2802)) ([ce56efe](https://github.com/santifer/career-ops/commit/ce56efe8ae6902924256c8257fe8b1b3ab3fdff7))
* **batch-tailor:** --min-score 4.5 was silently ignored, and the worker's pdf mode path was cwd-relative ([#2961](https://github.com/santifer/career-ops/issues/2961)) ([f306801](https://github.com/santifer/career-ops/commit/f30680152a54db92bf996120f08a91893a51db44))
* **batch:** retry state updates and lock reservations to prevent worker silent drops ([#2417](https://github.com/santifer/career-ops/issues/2417)) ([5404185](https://github.com/santifer/career-ops/commit/5404185deff59f8604014c63060458d0b22c640c))
* **build-cv-html:** render numeric year/date scalars instead of dropping them ([#2641](https://github.com/santifer/career-ops/issues/2641)) ([949a690](https://github.com/santifer/career-ops/commit/949a6900602d5df31aa2b7d1b7b40279de5b1fae))
* **build-cv-latex:** numeric year/date scalars are still dropped — [#2641](https://github.com/santifer/career-ops/issues/2641) fixed only the HTML mirror ([#2916](https://github.com/santifer/career-ops/issues/2916)) ([94eb334](https://github.com/santifer/career-ops/commit/94eb334a03a9837f4a98893e431f61b98264b609))
* **check-table-freshness:** validate CLI flags and add a usage block ([#2873](https://github.com/santifer/career-ops/issues/2873)) ([a12dd6b](https://github.com/santifer/career-ops/commit/a12dd6b355282f4801cd948f063525605c1545ed)), closes [#2855](https://github.com/santifer/career-ops/issues/2855)
* **ci:** only greet a first-time contributor when it is actually their first ([a0d45aa](https://github.com/santifer/career-ops/commit/a0d45aaaf4cf2770d702be8e1a3d7e115944aeb2))
* **ci:** skip the upgrade leg when nothing managed changed, instead of failing ([#2697](https://github.com/santifer/career-ops/issues/2697)) ([9dcfd2f](https://github.com/santifer/career-ops/commit/9dcfd2f668628879539c2ccfb3f17ce67f2824eb))
* **classify-tier:** an incidental senior word outranked an explicit intern marker ([#2737](https://github.com/santifer/career-ops/issues/2737)) ([cc2b1ce](https://github.com/santifer/career-ops/commit/cc2b1ce1edbc253f286da33ab9475adb9b46f22e))
* **cli:** a one-letter typo returned a false all-clear at exit 0 in 4 reporting CLIs ([#2920](https://github.com/santifer/career-ops/issues/2920)) ([d65d024](https://github.com/santifer/career-ops/commit/d65d0247183a10d115cedbf6dbda83dccf0fa765))
* **company-history:** record response dates via --on, not --note free text ([9b17a8a](https://github.com/santifer/career-ops/commit/9b17a8ac97b398a496b38e423ae24e433b43254f))
* **contacto:** LinkedIn connection-request limit is 200 on free tier, not 300 ([#2951](https://github.com/santifer/career-ops/issues/2951)) ([9c242c5](https://github.com/santifer/career-ops/commit/9c242c575ed0bd4d8e9591a3546b255464303f20))
* **csod:** replay bootstrap session cookies and repair fetchResponse() ([#2769](https://github.com/santifer/career-ops/issues/2769)) ([7aee3b9](https://github.com/santifer/career-ops/commit/7aee3b9f3bb44b8d4c34adf46a473afcc71ac97f))
* **cv-facts:** treat a k/M/B magnitude suffix as part of the number ([#2612](https://github.com/santifer/career-ops/issues/2612)) ([18d245a](https://github.com/santifer/career-ops/commit/18d245aa9edbfb99a6df90d5df8b6c63c971e549))
* **cv:** Korean and Traditional Chinese CVs had no font rule ([#2616](https://github.com/santifer/career-ops/issues/2616)) ([994552d](https://github.com/santifer/career-ops/commit/994552dc5d3faecacdf23f56e21e1b845fbf1aa7))
* **dedup-tracker:** reject unrecognized flags instead of silently live-running ([#2746](https://github.com/santifer/career-ops/issues/2746)) ([429b0dc](https://github.com/santifer/career-ops/commit/429b0dc8aa2418480c7c3548d7e67612564b960d))
* **deps:** make js-yaml imports work on both 4.x and 5.x ([#2656](https://github.com/santifer/career-ops/issues/2656)) ([6466b18](https://github.com/santifer/career-ops/commit/6466b18382aa2cb9390f5d2425a63ae36bcea085))
* **deps:** patch both HIGH advisories in web (js-yaml 4.3.1, nanoid 3.3.18) ([a094ec9](https://github.com/santifer/career-ops/commit/a094ec9ddbe8f21e8db6dba87f548532af2a820e))
* **deps:** raise the js-yaml floor to ^4.3.1 and guard it ([#2767](https://github.com/santifer/career-ops/issues/2767)) ([5b18a96](https://github.com/santifer/career-ops/commit/5b18a960da803477a475a1856138561f83edc035))
* **doctor:** detect Playwright MCP servers provided by Claude Code plugins ([#2753](https://github.com/santifer/career-ops/issues/2753)) ([49d20f2](https://github.com/santifer/career-ops/commit/49d20f26dff1b1f1d7d9c783bac714076ebc7444))
* **doctor:** validate CLI flags and add a usage block ([#2874](https://github.com/santifer/career-ops/issues/2874)) ([d4c31be](https://github.com/santifer/career-ops/commit/d4c31be403453249abe039c3ebc50cb7e56f7539)), closes [#2856](https://github.com/santifer/career-ops/issues/2856)
* **eval:** merge openrouter tracker TSVs and send Ollama options to the native /api/chat ([#2647](https://github.com/santifer/career-ops/issues/2647)) ([a86f776](https://github.com/santifer/career-ops/commit/a86f776a252ec1fa608dcd3ab61c4f6f1b678754))
* **find:** print the one USAGE constant on the empty-query path too ([f0dd6ed](https://github.com/santifer/career-ops/commit/f0dd6edb9387f1b8ff4bbb4b69e62f8982fc3f7c))
* **find:** reject mistyped flags instead of searching for them ([9265e08](https://github.com/santifer/career-ops/commit/9265e08188719bbf06891c8efc2ae10fa0991b63))
* **followup-cadence:** parse annotated pins, and add a retire directive ([#2514](https://github.com/santifer/career-ops/issues/2514)) ([b4f6b2d](https://github.com/santifer/career-ops/commit/b4f6b2dd4b55c8172e56ef776f1e4fd82bce4acf))
* **followup-seed:** resolve "today" in local time, not UTC ([#2765](https://github.com/santifer/career-ops/issues/2765)) ([15aa769](https://github.com/santifer/career-ops/commit/15aa7697292d3afe2fc557626beda74a12a4523a))
* **followup:** ignore an apply date cited about another row ([#2610](https://github.com/santifer/career-ops/issues/2610)) ([53808a9](https://github.com/santifer/career-ops/commit/53808a91745594685be3118e1792aa4ad0e6ee51)), closes [#2607](https://github.com/santifer/career-ops/issues/2607)
* **invite-match:** validate CLI flags and add usage ([#2958](https://github.com/santifer/career-ops/issues/2958)) ([34b1d58](https://github.com/santifer/career-ops/commit/34b1d58ff954b83f7cb797317c1bbc5aaafdacd8))
* **jd-similarity:** add --help and reject unknown flags instead of reading them as paths ([#2819](https://github.com/santifer/career-ops/issues/2819)) ([ce1f321](https://github.com/santifer/career-ops/commit/ce1f321388b4f2c36f2dd112da2e7d99abdc44ba)), closes [#2772](https://github.com/santifer/career-ops/issues/2772)
* **jd-similarity:** the seniority gate fired on JD boilerplate ([#2661](https://github.com/santifer/career-ops/issues/2661)) ([772ea35](https://github.com/santifer/career-ops/commit/772ea35153f88a101c3d22da1741cb79804fae4d))
* **jd-skill-gap:** recognize all six markdown heading levels ([#2721](https://github.com/santifer/career-ops/issues/2721)) ([2a3bd2f](https://github.com/santifer/career-ops/commit/2a3bd2f1f75580824ee0be1f26e93d54f0be18af))
* **jd-skill-gap:** recognize sentence-form requirement headings ([#2686](https://github.com/santifer/career-ops/issues/2686)) ([fd9ca41](https://github.com/santifer/career-ops/commit/fd9ca41d372886b1c095b8ba689e48950da6260f))
* **jobvite:** migrate to the public XML feed after the JSON API retirement ([#2623](https://github.com/santifer/career-ops/issues/2623)) ([0c7522b](https://github.com/santifer/career-ops/commit/0c7522b408f0f62d334972a34fcf1ece2a55541c))
* **keys:** stop the dotted-I fix from collapsing Polish, Lithuanian and Maltese ([5df43e7](https://github.com/santifer/career-ops/commit/5df43e7133745ad814421f2dd4c5afce2e75c0e1))
* **keys:** stop the Turkish dotted capital from splitting one employer in two ([462d276](https://github.com/santifer/career-ops/commit/462d27653eda17c3305dfe74f2ecdc5b21fb79e6))
* **liveness:** classify a rate-limited posting as uncertain, not expired ([#2613](https://github.com/santifer/career-ops/issues/2613)) ([c65afe6](https://github.com/santifer/career-ops/commit/c65afe6f508105d84da75fddb026b077afd9bbc0))
* **liveness:** treat an api.lever.co 404 as inconclusive, not proof of removal ([#2649](https://github.com/santifer/career-ops/issues/2649)) ([84fe20f](https://github.com/santifer/career-ops/commit/84fe20f0cebc6500fc85939752ff946dc43e1de7))
* **locks:** treat Windows rm/stat contention as contention, not death ([#2984](https://github.com/santifer/career-ops/issues/2984)) ([2743281](https://github.com/santifer/career-ops/commit/27432818d29faf67103714e12f6777bf39239c67))
* **match-star:** score a non-English story bank against a question in its own language ([#2848](https://github.com/santifer/career-ops/issues/2848)) ([fa5926d](https://github.com/santifer/career-ops/commit/fa5926df06c348e18459a6c8f5328c93c8641d5a))
* **merge-tracker:** deterministic dedup on the posting URL ([#1298](https://github.com/santifer/career-ops/issues/1298)) ([a0426bb](https://github.com/santifer/career-ops/commit/a0426bb9ef06744f59d67e17014dd4c7fda59e17))
* **merge-tracker:** match inline URL headers so URL dedup activates for doc-style rows ([#2926](https://github.com/santifer/career-ops/issues/2926)) ([c078513](https://github.com/santifer/career-ops/commit/c078513127aa13bd02edb2a2cbadad34da20615b))
* **merge-tracker:** re-eval no longer inherits the superseded report's checkmark ([#2595](https://github.com/santifer/career-ops/issues/2595)) ([c85d02f](https://github.com/santifer/career-ops/commit/c85d02fda92f93d3d97fe273b05059397be1ab87))
* **ollama:** include profile context in evaluations ([#2664](https://github.com/santifer/career-ops/issues/2664)) ([ef2a82f](https://github.com/santifer/career-ops/commit/ef2a82f6970302733c35ebba9b3a30ec5fac65f1))
* **oraclecloud:** accept Oracle's numbered tenant apexes (oraclecloud1-99.com) ([#2683](https://github.com/santifer/career-ops/issues/2683)) ([a23ebc1](https://github.com/santifer/career-ops/commit/a23ebc1a2f88a16db98af9f3a16e8c4041b5bded))
* **patterns:** rate denominators counted rows that could never contribute ([#2783](https://github.com/santifer/career-ops/issues/2783)) ([e2dbbbf](https://github.com/santifer/career-ops/commit/e2dbbbfcd79c205a5589be0907921d846e299ddb))
* **pipeline-lock:** a non-EEXIST mkdir refusal is contention, not a fatal error ([#2838](https://github.com/santifer/career-ops/issues/2838)) ([bca798f](https://github.com/santifer/career-ops/commit/bca798f8a61b1bbcd93da17c04d17eccbba627b6)), closes [#2777](https://github.com/santifer/career-ops/issues/2777)
* **pipeline-lock:** jitter the retry so a starved writer costs a retry, not an item ([c7dbf0d](https://github.com/santifer/career-ops/commit/c7dbf0d9b7fed227129340055655303a955b567b))
* **plugin-audit:** validate CLI arguments and add a usage block ([#2813](https://github.com/santifer/career-ops/issues/2813)) ([588139c](https://github.com/santifer/career-ops/commit/588139c629eab04c69a868469b921cb01b013ae3)), closes [#2771](https://github.com/santifer/career-ops/issues/2771)
* **process-quality:** three undisclosed employers were reported as disclosed ([#3005](https://github.com/santifer/career-ops/issues/3005)) ([b5acfa5](https://github.com/santifer/career-ops/commit/b5acfa513bc16896f0310affaa835c4a1bb21f04))
* **providers:** decode HTML entities in titles before matching so encoded ampersands stop dropping jobs ([#2923](https://github.com/santifer/career-ops/issues/2923)) ([37f4c11](https://github.com/santifer/career-ops/commit/37f4c11b4ad5e3aca94aa389453806b3a6210535))
* **providers:** fill in the docs and vendor-detection gaps ([#2658](https://github.com/santifer/career-ops/issues/2658)) ([7152907](https://github.com/santifer/career-ops/commit/7152907e88fd2daa05c83f8351ea873f8296e072))
* **providers:** harden workable with retry, headers, and serialization ([#2675](https://github.com/santifer/career-ops/issues/2675)) ([feabcd4](https://github.com/santifer/career-ops/commit/feabcd45b3615af6d8871f89f17246dbbab3a811))
* **providers:** isRetryableError no longer misclassifies a refused redirect ([#2657](https://github.com/santifer/career-ops/issues/2657)) ([f8feaa5](https://github.com/santifer/career-ops/commit/f8feaa53c3f7bb8cf0cc33196d0ca3bf999951da))
* **providers:** make themuse resilient to per-page fetch failures ([#2682](https://github.com/santifer/career-ops/issues/2682)) ([a83800f](https://github.com/santifer/career-ops/commit/a83800feac3c15017365c6d6b6acb69509757f20))
* **providers:** personio falls back to HTML scrape when the XML feed is disabled ([5fe2784](https://github.com/santifer/career-ops/commit/5fe27841b7839d7b8ea5a7f5c753408b4f24f03c))
* **providers:** phenom pagination/retry fixes, drop dead auto-detection ([#2669](https://github.com/santifer/career-ops/issues/2669)) ([1331ebf](https://github.com/santifer/career-ops/commit/1331ebfcb805d3714d2e6c81b2b9e22395b80540))
* **providers:** reject numeric entities outside the XML 1.0 Char set ([#2713](https://github.com/santifer/career-ops/issues/2713)) ([a050631](https://github.com/santifer/career-ops/commit/a0506312b67a26560022415b5b5abdf3a99ca8ad))
* **providers:** route seven RSS decoders through the shared safe entity decoder ([#2818](https://github.com/santifer/career-ops/issues/2818)) ([5b00081](https://github.com/santifer/career-ops/commit/5b00081f1a74354c1924177985d1576e50ddcef1)), closes [#2790](https://github.com/santifer/career-ops/issues/2790)
* **providers:** route softgarden and radancy through the shared entity decoder ([#2487](https://github.com/santifer/career-ops/issues/2487)) ([96b1de6](https://github.com/santifer/career-ops/commit/96b1de6806dd2630f4c26b19cf37c6ca98638d07))
* **reply-matcher:** require corroboration for partial role-title matches ([#2672](https://github.com/santifer/career-ops/issues/2672)) ([3215fa3](https://github.com/santifer/career-ops/commit/3215fa309d5158d2ea51a97a5074792e1d9138d7))
* **reply-matcher:** the '?' unknown-employer placeholder matched everything ([#3001](https://github.com/santifer/career-ops/issues/3001)) ([86e653d](https://github.com/santifer/career-ops/commit/86e653d5b08bbf81781c0f84b6c567dbe79e571f))
* **reply-watch:** reject unrecognized CLI flags instead of treating them as a path ([#2745](https://github.com/santifer/career-ops/issues/2745)) ([ba2b634](https://github.com/santifer/career-ops/commit/ba2b6340d8802125789203e5f2deb5084c04857b))
* **reserve-report-num:** do not read a bare date file as a report number ([#2759](https://github.com/santifer/career-ops/issues/2759)) ([6d6524b](https://github.com/santifer/career-ops/commit/6d6524b30694c7a870df3aacdf7075ce524c4ee8)), closes [#2757](https://github.com/santifer/career-ops/issues/2757)
* **role-matcher:** tokenize non-Latin role titles and scope the mark fold ([#2782](https://github.com/santifer/career-ops/issues/2782)) ([6704dd6](https://github.com/santifer/career-ops/commit/6704dd6cf4fc957c9a4a085459ee64ba73fc8f7c)), closes [#2781](https://github.com/santifer/career-ops/issues/2781)
* **scan-ats-full:** cap single-host ATS sweeps at their own concurrency ([#2839](https://github.com/santifer/career-ops/issues/2839)) ([5ef0676](https://github.com/santifer/career-ops/commit/5ef0676a3b304e48325031070358d547d65b70de))
* **scan:** locate the URL anywhere in a pipeline.md entry ([#2605](https://github.com/santifer/career-ops/issues/2605)) ([c0413e3](https://github.com/santifer/career-ops/commit/c0413e3ce374b2e6be628a46f9b28422e26d3e85))
* **scan:** take the shared lock for scan-history.tsv appends ([#2639](https://github.com/santifer/career-ops/issues/2639)) ([8e264c4](https://github.com/santifer/career-ops/commit/8e264c4b24a04fc6f0799b2e5c9a0479ed4e16e0))
* **set-status:** stop the --role guard from folding every non-Latin title to the same key ([#2736](https://github.com/santifer/career-ops/issues/2736)) ([437da7a](https://github.com/santifer/career-ops/commit/437da7aa2cfaacb0ca9161303627ea7f3ee85569))
* **states:** aliases the engine accepts were missing from states.yml ([#2615](https://github.com/santifer/career-ops/issues/2615)) ([04ef492](https://github.com/santifer/career-ops/commit/04ef4925c8271112cfcd9711405b7bbc3ae3025f))
* **status:** fold Turkish dotted capitals so uppercase tracker rows resolve to canonical states ([0834e72](https://github.com/santifer/career-ops/commit/0834e7224b99a130ac09ea6a076f585aac85e85d))
* **tests:** contain a discovered suite that throws at import ([#2830](https://github.com/santifer/career-ops/issues/2830)) ([51e8f19](https://github.com/santifer/career-ops/commit/51e8f19513d5cc9e9f26b3a27442f32cebf9e678))
* **theme-style:** a `$`-pattern in a profile style value splices the body into the CV's  ([1798f3a](https://github.com/santifer/career-ops/commit/1798f3a45e5ec8eb44af634dce5f6703a9c6d874))
* **update:** commit the index so file-mode changes are not dropped ([#2629](https://github.com/santifer/career-ops/issues/2629)) ([4b1d66b](https://github.com/santifer/career-ops/commit/4b1d66b22249506442906e673405bcfed7c58a57))
* **update:** ignore CRLF/LF-only differences when detecting local system edits ([#2820](https://github.com/santifer/career-ops/issues/2820)) ([9c06337](https://github.com/santifer/career-ops/commit/9c0633733c74453da0062a66e4dca3b76ba96741)), closes [#2817](https://github.com/santifer/career-ops/issues/2817)
* **update:** reconcile .gitignore on apply so new ignore rules reach existing installs ([#2857](https://github.com/santifer/career-ops/issues/2857)) ([2728cd0](https://github.com/santifer/career-ops/commit/2728cd0d40f0f640856e898aadc6999d05a8d2ba))
* **velocity:** count a web-written transition as an observation ([#2898](https://github.com/santifer/career-ops/issues/2898)) ([2e36380](https://github.com/santifer/career-ops/commit/2e363807429322c6f660b011d4b56b3222e3c3cb))
* **verify-cv-facts:** fold allow_metrics through the same noun synonyms ([#2720](https://github.com/santifer/career-ops/issues/2720)) ([5352f38](https://github.com/santifer/career-ops/commit/5352f380c550a0551165cb9f9c7194f0fd15dfdb))
* **verify-cv-facts:** treat a period as a thousands separator too ([#2722](https://github.com/santifer/career-ops/issues/2722)) ([dceaddb](https://github.com/santifer/career-ops/commit/dceaddb3739173ca9f526851c16cdfa6cd717db1))
* **voice-dna:** make voice-dna.md private via the template pattern ([#2952](https://github.com/santifer/career-ops/issues/2952)) ([10a9c55](https://github.com/santifer/career-ops/commit/10a9c55147fb1a3ae6a7741f41fad59b68c79722))
* **web:** add Grok Build CLI to the web runtime picker ([#2688](https://github.com/santifer/career-ops/issues/2688)) ([af0d818](https://github.com/santifer/career-ops/commit/af0d8183937a43397a127e75967b906fece86364))
* **web:** analytics tells an offer-holder they have 0 interviews (and nudges them to try harder) ([#2410](https://github.com/santifer/career-ops/issues/2410)) ([8f2b415](https://github.com/santifer/career-ops/commit/8f2b41505997c0f15d86ee617304701239328a12))
* **web:** anchor the fallback stderr classifier so a word can't fail a run ([#2882](https://github.com/santifer/career-ops/issues/2882)) ([be62e3e](https://github.com/santifer/career-ops/commit/be62e3ef28fcbcc18f1cddec3269c8da00be645c))
* **web:** carry the posted: segment so web evaluations reach the POSTED column ([#2899](https://github.com/santifer/career-ops/issues/2899)) ([6eece73](https://github.com/santifer/career-ops/commit/6eece731b36ea91286e984289518839d9ab5c342))
* **web:** detect OpenCode in its default install directory ([#1794](https://github.com/santifer/career-ops/issues/1794)) ([c10b887](https://github.com/santifer/career-ops/commit/c10b88764a793e4176688f60aa066e96eff1c3a4))
* **web:** emit the posting URL in the tracker-additions TSV so web runs join the dedup ([#2833](https://github.com/santifer/career-ops/issues/2833)) ([3c68721](https://github.com/santifer/career-ops/commit/3c68721fc28b98fc127ff9f5a36ac71188215750))
* **web:** enforce that no runtime grants itself blanket write permission ([#2875](https://github.com/santifer/career-ops/issues/2875)) ([9ba6ebf](https://github.com/santifer/career-ops/commit/9ba6ebf2f94dbd2772af9b32572af25429b303fc))
* **web:** finish Unicode company keys for explore + registry ([#2668](https://github.com/santifer/career-ops/issues/2668)) ([c294242](https://github.com/santifer/career-ops/commit/c294242dbb6a78a03bac738f397c568c02316971))
* **web:** fold Turkish dotted capitals in status keys, and stop hand-copying the state list ([#2786](https://github.com/santifer/career-ops/issues/2786)) ([e1a0961](https://github.com/santifer/career-ops/commit/e1a09616818d2dd84b249a7805078bbfeefae669))
* **web:** keep Codex JSONL + exit code authoritative for web scoring ([#2102](https://github.com/santifer/career-ops/issues/2102)) ([2d43601](https://github.com/santifer/career-ops/commit/2d436019b60484e97576dd36e9ce324d2585cd6a))
* **web:** let the pipeline table scroll horizontally instead of clipping on narrow screens ([#2363](https://github.com/santifer/career-ops/issues/2363)) ([632031c](https://github.com/santifer/career-ops/commit/632031c9cb8ae95311a36310bb6cd2713497136c))
* **web:** make the tracker reader agree with parseTrackerRow on row shape ([#2565](https://github.com/santifer/career-ops/issues/2565)) ([4fea438](https://github.com/santifer/career-ops/commit/4fea43835e940be62011f12afab4f35cb265c4ac))
* **web:** prevent Codex run jobs from waiting on stdin ([#1973](https://github.com/santifer/career-ops/issues/1973)) ([9a139a2](https://github.com/santifer/career-ops/commit/9a139a2aac44ae5e8da8e372a587a322ba99f149))
* **web:** read target_roles with the shape it is actually written in ([#2750](https://github.com/santifer/career-ops/issues/2750)) ([5f5c06d](https://github.com/santifer/career-ops/commit/5f5c06d4b257b4ef55dfedc2f1d1c0eb26bc9789))
* **web:** show the retry card, not the update-checkout panel, for runtime scan errors ([#1904](https://github.com/santifer/career-ops/issues/1904)) ([29c0d69](https://github.com/santifer/career-ops/commit/29c0d69cb0e2c2c3507e2712eaf04f1633244722))
* **web:** skip {n}-RESERVED.md sentinels when looking up reports ([#1967](https://github.com/santifer/career-ops/issues/1967)) ([5f4842e](https://github.com/santifer/career-ops/commit/5f4842e513fe45092395254ba51bc220676e598a))
* **web:** stop the 16-chip cap from truncating the user's own portals.yml ([#2749](https://github.com/santifer/career-ops/issues/2749)) ([a5af949](https://github.com/santifer/career-ops/commit/a5af94900b981105f2560ee271e22a00479093a9))
* **web:** strip the author letter from any lettered block, not just A-G ([#2420](https://github.com/santifer/career-ops/issues/2420)) ([630709a](https://github.com/santifer/career-ops/commit/630709a3cad0297b7305752cfdf6ed5b0469b4d8))
* **web:** take the core tracker lock in POST /api/status ([#2903](https://github.com/santifer/career-ops/issues/2903)) ([d9c4fd0](https://github.com/santifer/career-ops/commit/d9c4fd0a0fa191717f1f68663b5eaa11c0351ea6))
* **workday:** key the cap-hit warning on entry provenance, not on --since ([#2763](https://github.com/santifer/career-ops/issues/2763)) ([7f067bc](https://github.com/santifer/career-ops/commit/7f067bce916a964411e27948b06227c4ca39bfd2))


### Performance Improvements

* **analytics:** drop redundant existsSync probes before report reads ([#2655](https://github.com/santifer/career-ops/issues/2655)) ([f06cbf8](https://github.com/santifer/career-ops/commit/f06cbf81bba797bc1cd758bca3d71866c80d9b9e))
* **scan:** read each dedup source once per scan run ([d68c4c9](https://github.com/santifer/career-ops/commit/d68c4c963592787df3b7a34d4e5f9bb48010415b))


web: 0.7.0

## [0.7.0](https://github.com/santifer/career-ops/compare/web-v0.6.1...web-v0.7.0) (2026-08-18)


### Features

* **web:** give the Apply page a way back and a way to record that you applied ([#2735](https://github.com/santifer/career-ops/issues/2735)) ([05cc972](https://github.com/santifer/career-ops/commit/05cc972c2d45471ba45a8457c83f488915fc4fa6))


### Bug Fixes

* **deps:** make js-yaml imports work on both 4.x and 5.x ([#2656](https://github.com/santifer/career-ops/issues/2656)) ([6466b18](https://github.com/santifer/career-ops/commit/6466b18382aa2cb9390f5d2425a63ae36bcea085))
* **deps:** patch both HIGH advisories in web (js-yaml 4.3.1, nanoid 3.3.18) ([a094ec9](https://github.com/santifer/career-ops/commit/a094ec9ddbe8f21e8db6dba87f548532af2a820e))
* **deps:** raise the js-yaml floor to ^4.3.1 and guard it ([#2767](https://github.com/santifer/career-ops/issues/2767)) ([5b18a96](https://github.com/santifer/career-ops/commit/5b18a960da803477a475a1856138561f83edc035))
* **keys:** stop the dotted-I fix from collapsing Polish, Lithuanian and Maltese ([5df43e7](https://github.com/santifer/career-ops/commit/5df43e7133745ad814421f2dd4c5afce2e75c0e1))
* **keys:** stop the Turkish dotted capital from splitting one employer in two ([462d276](https://github.com/santifer/career-ops/commit/462d27653eda17c3305dfe74f2ecdc5b21fb79e6))
* **scan:** take the shared lock for scan-history.tsv appends ([#2639](https://github.com/santifer/career-ops/issues/2639)) ([8e264c4](https://github.com/santifer/career-ops/commit/8e264c4b24a04fc6f0799b2e5c9a0479ed4e16e0))
* **web:** add Grok Build CLI to the web runtime picker ([#2688](https://github.com/santifer/career-ops/issues/2688)) ([af0d818](https://github.com/santifer/career-ops/commit/af0d8183937a43397a127e75967b906fece86364))
* **web:** analytics tells an offer-holder they have 0 interviews (and nudges them to try harder) ([#2410](https://github.com/santifer/career-ops/issues/2410)) ([8f2b415](https://github.com/santifer/career-ops/commit/8f2b41505997c0f15d86ee617304701239328a12))
* **web:** anchor the fallback stderr classifier so a word can't fail a run ([#2882](https://github.com/santifer/career-ops/issues/2882)) ([be62e3e](https://github.com/santifer/career-ops/commit/be62e3ef28fcbcc18f1cddec3269c8da00be645c))
* **web:** carry the posted: segment so web evaluations reach the POSTED column ([#2899](https://github.com/santifer/career-ops/issues/2899)) ([6eece73](https://github.com/santifer/career-ops/commit/6eece731b36ea91286e984289518839d9ab5c342))
* **web:** detect OpenCode in its default install directory ([#1794](https://github.com/santifer/career-ops/issues/1794)) ([c10b887](https://github.com/santifer/career-ops/commit/c10b88764a793e4176688f60aa066e96eff1c3a4))
* **web:** emit the posting URL in the tracker-additions TSV so web runs join the dedup ([#2833](https://github.com/santifer/career-ops/issues/2833)) ([3c68721](https://github.com/santifer/career-ops/commit/3c68721fc28b98fc127ff9f5a36ac71188215750))
* **web:** enforce that no runtime grants itself blanket write permission ([#2875](https://github.com/santifer/career-ops/issues/2875)) ([9ba6ebf](https://github.com/santifer/career-ops/commit/9ba6ebf2f94dbd2772af9b32572af25429b303fc))
* **web:** finish Unicode company keys for explore + registry ([#2668](https://github.com/santifer/career-ops/issues/2668)) ([c294242](https://github.com/santifer/career-ops/commit/c294242dbb6a78a03bac738f397c568c02316971))
* **web:** fold Turkish dotted capitals in status keys, and stop hand-copying the state list ([#2786](https://github.com/santifer/career-ops/issues/2786)) ([e1a0961](https://github.com/santifer/career-ops/commit/e1a09616818d2dd84b249a7805078bbfeefae669))
* **web:** keep Codex JSONL + exit code authoritative for web scoring ([#2102](https://github.com/santifer/career-ops/issues/2102)) ([2d43601](https://github.com/santifer/career-ops/commit/2d436019b60484e97576dd36e9ce324d2585cd6a))
* **web:** let the pipeline table scroll horizontally instead of clipping on narrow screens ([#2363](https://github.com/santifer/career-ops/issues/2363)) ([632031c](https://github.com/santifer/career-ops/commit/632031c9cb8ae95311a36310bb6cd2713497136c))
* **web:** make the tracker reader agree with parseTrackerRow on row shape ([#2565](https://github.com/santifer/career-ops/issues/2565)) ([4fea438](https://github.com/santifer/career-ops/commit/4fea43835e940be62011f12afab4f35cb265c4ac))
* **web:** prevent Codex run jobs from waiting on stdin ([#1973](https://github.com/santifer/career-ops/issues/1973)) ([9a139a2](https://github.com/santifer/career-ops/commit/9a139a2aac44ae5e8da8e372a587a322ba99f149))
* **web:** read target_roles with the shape it is actually written in ([#2750](https://github.com/santifer/career-ops/issues/2750)) ([5f5c06d](https://github.com/santifer/career-ops/commit/5f5c06d4b257b4ef55dfedc2f1d1c0eb26bc9789))
* **web:** show the retry card, not the update-checkout panel, for runtime scan errors ([#1904](https://github.com/santifer/career-ops/issues/1904)) ([29c0d69](https://github.com/santifer/career-ops/commit/29c0d69cb0e2c2c3507e2712eaf04f1633244722))
* **web:** skip {n}-RESERVED.md sentinels when looking up reports ([#1967](https://github.com/santifer/career-ops/issues/1967)) ([5f4842e](https://github.com/santifer/career-ops/commit/5f4842e513fe45092395254ba51bc220676e598a))
* **web:** stop the 16-chip cap from truncating the user's own portals.yml ([#2749](https://github.com/santifer/career-ops/issues/2749)) ([a5af949](https://github.com/santifer/career-ops/commit/a5af94900b981105f2560ee271e22a00479093a9))
* **web:** strip the author letter from any lettered block, not just A-G ([#2420](https://github.com/santifer/career-ops/issues/2420)) ([630709a](https://github.com/santifer/career-ops/commit/630709a3cad0297b7305752cfdf6ed5b0469b4d8))
* **web:** take the core tracker lock in POST /api/status ([#2903](https://github.com/santifer/career-ops/issues/2903)) ([d9c4fd0](https://github.com/santifer/career-ops/commit/d9c4fd0a0fa191717f1f68663b5eaa11c0351ea6))