更新日誌

GitHub

每一項重大變更,逐版記錄。同一份檔案隨儲存庫發布,並已翻譯為全部 19 種語言。

[1.114.0] — 2026-07-06

側邊欄中的 AI 用量與費用計量(左下)。 一個精簡的用量區塊現在位於每個頁面側邊欄底部(無側邊欄時為左下角固定卡片;RTL 中為右下角)。它按 24h / 7d / 30d 視窗展示 LLM 權杖用量——每個為 <權杖> · <占比%>(占全時段比例)配綠色進度條——並附 24 小時預估費用頁尾。資料來自 data/llm-usage.jsonl 的唯讀 GET /api/usage 彙總(僅本地),與 #/usage 頁面同源;費用為估算,手動模式執行免費且不計入。可折疊——點擊標題切換,狀態會保存。

  • 新用戶端元件 public/js/lib/usage-hud.js,從 index.html 載入,掛載到版本頁尾上方的側邊欄(固定角落回退)。CSP 安全;主題感知 + RTL 鏡像。無新伺服器路由。測試:tests/usage-hud.test.mjs(8)。新增 3 個 i18n 鍵 ×16。

新增:無。

[1.113.0] — 2026-07-06

每個頁面上浮動的「詢問說明」助手。 一個漸層機器人聊天按鈕現在浮動在每個頁面的右下角(RTL 中在左下角)。點擊即可開啟一個精簡聊天,它僅根據你語言的應用內說明指南回答使用類問題——與 #/docs-assistant 頁面相同的端點(POST /api/docs-assistant/ask),因此從不讀取你的履歷、資料或追蹤器。有 LLM 金鑰時即時回答;無金鑰則給出可直接執行的提示詞。標題顯示機器人頭像 + 線上狀態;起始徽章填入常見問題;Esc 或點擊外部關閉;在 #/docs-assistant 頁面上自動隱藏。

  • 新用戶端元件 public/js/lib/docs-fab.js,從 index.html 全域掛載;CSP 安全;app.css 中主題感知 + RTL 鏡像樣式。無新伺服器路由。測試:tests/docs-fab.test.mjs(8)。新增 6 個 i18n 鍵 ×16。說明 §1 就地擴充。

新增:無。

[1.112.0] — 2026-07-06

文件與 QA 整合。 無使用者可見的程式碼改動。SDD 慣例文件(docs/sdd/CONVENTIONS.md)更新到目前的 30 個路由模組(先前 24 個)和目前測試基準;全專案權威 QA 提示詞(qa/QA-REGRESSION-PROMPT.md)已整合——發布流程去陳舊化(v1.111、parentVersion 1.17.0、由發布事件觸發的發布),§14 新增表修正(Scan 排除重新標註為 v1.109.0)並補入 v1.111 的 CodeQL 收尾——因而可獨立作為涵蓋所有功能的單一回歸提示詞。新增一個針對超大上傳分支的覆蓋測試。

新增:無。

[1.111.0] — 2026-07-06

安全 — 清理 CodeQL 待辦。 三項縱深防禦強化,從根源關閉剩餘的靜態分析發現,而非將其忽略(dismiss)。stripDangerousMarkdown 現在會逸出任何被截斷的危險標籤開頭(以 <script/<iframe/… 結尾的載荷)的 <,從而可證明其輸出不含任何存活的危險標籤。CV 匯入透過明確的 Number() 強制轉換讀取上傳緩衝區的大小——一道型別混淆屏障。模式角色行現在是用 String.replace 插值的範本字串,而非儲存的函式,徹底移除了動態派發呼叫。使用者可見行為無變化。

  • server/lib/security.mjs、server/lib/cv-import.mjs、server/lib/prompts.mjs。測試:tests/security-hardening-v1111.test.mjs(7)+ 更新的 v1108 守衛測試。無 i18n/說明/路由改動。

新增:無。

[1.110.0] — 2026-07-06

文件與 QA 刷新(所有語言)。 無程式碼改動。全專案 QA 提示詞刷新至 v1.109.0,新增涵蓋 v1.98→v1.109 的 §14,常駐 UX 稽核與設計匯出提示詞納入目前頁面集。v1.100–v1.109 新增的每個說明段落現已翻譯為全部 16 種語言。

新增: 無.

[1.109.0] — 2026-07-06

Scan 排除篩選 + 流水線概覽(Web 版面對齊)。 在 #/scan 上,搜尋框現在把逗號視為或(「要找的職位」),新增的排除欄位會隱藏公司/職位/地點包含任一逗號分隔詞(如 senior, staff)的列;兩者都會記入你的已儲存搜尋。在 #/pipeline 上,一個精簡的概覽列一眼展示流水線——收件匣 N、已追蹤 N,以及來自追蹤器的 Applied / Responded / Interview / Offer 計數,每個徽章連結到 #/tracker。

  • 僅用戶端(無新路由/寫入)。public/js/views/scan.js + public/js/views/pipeline.js。測試:tests/scan-pipeline-ui-v1109.test.mjs(2)。新增 4 個 i18n 鍵 ×16。說明 §7 + §8 就地擴充。

新增:無。

[1.108.0] — 2026-07-06

安全強化(CodeQL 分診第 2 輪)。 又修復三處低危問題:模式提示建構器按自有鍵 + typeof === function解析語言角色行,使被竄改的語言無法分派到原型方法(unvalidated-dynamic-method-call);PDF 檔名 slug 在正規式之前限制為 200 字元,使全連字號輸入無法回溯(多項式 ReDoS);文件匯入將陣列 filename(重複標頭)強制轉換為字串(type-confusion)。對有效輸入無行為變化。

  • server/lib/prompts.mjs、server/lib/routes/runners.mjs、server/lib/cv-import.mjs + tests/security-hardening-v1108.test.mjs(3)。v1.106–v1.108 期間靜態分析積壓從 167 降至約 14,所有真正與安全相關的發現均已修復,其餘(有防護/已淨化的誤報 + 註解級 lint)已附理由駁回。

新增:無。

[1.107.0] — 2026-07-06

淨化器強化(靜態 XSS 縱深防禦)。 stripDangerousMarkdown——中和已儲存的履歷/職缺 markdown 中的危險 HTML,使任何繞過渲染時跳脫用戶端的消費者仍然安全——現在會將標籤清除執行至不動點(重複直到穩定),以便捕捉會重構酬載的清除(如 <scr<script></script>ipt>),匹配末尾帶雜物的 script/style 等結束標籤(</script foo>),並清除未閉合的可執行開標籤(<script …>)。對有效 markdown 的行為不變——只會清除更多。

  • server/lib/security.mjs:不動點迴圈(限 8 輪)+ [^>]*> 結束標籤模式 + 未閉合開標籤清除。tests/cv-xss-bypasses.test.mjs +3 迴歸用例。權威的 XSS 邊界仍是輸出跳脫(UI.md);這加強了靜態保證並關閉了相應的 CodeQL 發現。

新增:無。

[1.106.0] — 2026-07-06

安全強化(CodeQL 分診)。 梳理靜態分析積壓後修復了三處真實(儘管低危)問題:路由渲染的錯誤路徑現在會在錯誤訊息到達 DOM 之前進行跳脫(伺服器錯誤可能回顯使用者輸入,故視為不可信——XSS 邊界),檔案/設定的屬性寫入會拒絕 __proto__ / constructor / prototype 鍵(以防萬一的原型汙染防護——鍵來自固定欄位規格,而非原始請求輸入)。其餘警示多為對掃描器合法讀寫 data/* 以及已帶自有限流器的路由的誤報,已附理由駁回。

  • public/js/router.js 在 innerHTML 之前用 UI.escapeHtml 跳脫 err.message;server/lib/routes/content.mjs 和 server/lib/routes/config.mjs 防護原型鍵。對有效輸入無行為變化。測試:tests/security-hardening-v1106.test.mjs(3)。無新增 i18n 鍵。

新增:無。

[1.105.0] — 2026-07-06

AI 用量與成本頁面。 新的AI 用量頁面(側邊欄,健康旁邊)顯示你在即時 AI 生成(評估、報告、對話)上花費的權杖,按供應商分列,涵蓋最近 24 小時、7 天、30 天和全部時間,並附預計 USD 成本。每次即時呼叫都會向 data/llm-usage.jsonl 追加一條小記錄 {provider, in, out}(不向任何地方傳送);無金鑰執行(手動模式)不產生費用,也不記錄。

  • 新路由模組(第 30 個) server/lib/routes/usage.mjs — GET /api/usage(唯讀彙總) + server/lib/llm-usage.mjs(recordUsage 正規化 Anthropic/OpenAI/Gemini 的用量結構並盡力追加;readUsage/aggregate 按 24h/7d/30d/全部視窗 × 供應商彙總) + server/lib/llm-pricing.mjs(可編輯的各供應商 $/1M 權杖價格表——權杖數精確,美元為可修改的近似標價,不計費)。記錄掛接在分發點(runActiveProvider + routes/llm.mjs)。
  • 新檢視 public/js/views/usage.js(#/usage,時間窗分頁)。測試:tests/usage-routes.test.mjs。新增 17 個 i18n 鍵 ×16(usage.* + nav.usage)。說明 §6 就地擴充。

新增:server/lib/routes/usage.mjs;server/lib/llm-usage.mjs;server/lib/llm-pricing.mjs;public/js/views/usage.js。

[1.104.0] — 2026-07-06

掃描表中的公司標誌(保護隱私)。 應用設定中新增的外觀開關——在掃描表中顯示公司標誌(預設關閉)——會在 #/scan 的公司名稱旁繪製其標誌。標誌是從公司自己網域取得的 favicon,並在伺服器端代理(GET /api/logo),因此沒有任何第三方標誌服務能得知你在查看哪些雇主。位於共享徵才入口(Greenhouse、Lever、Ashby 等)的職缺會顯示彩色字母徽章而非入口圖示,任何載入失敗的標誌也回退到同一徽章。

  • 新路由模組(第 29 個) server/lib/routes/logos.mjs — GET /api/logo?domain=。它驗證網域(無協定/路徑/回環),透過 SSRF 安全的 safeGet(新的 binary 模式回傳原始位元組 + content-type;DNS 固定、重新導向驗證和大小上限不變)取得 /favicon.ico,進行影像魔數嗅探以絕不把 HTML 錯誤頁當作影像回傳,將命中與未命中都快取在記憶體 LRU 中,並不向磁碟寫入任何內容。
  • 新客戶端庫 public/js/lib/company-logo.js(window.CompanyLogo):透過 localStorage 旗標預設關閉;跳過共享 ATS 主機改用確定性字母頭像;CSP 安全的 img.onerror 回退。測試:tests/logo-routes.test.mjs。新增 5 個 i18n 鍵 ×16(appear.*)。說明 §2 就地擴充。

新增:server/lib/routes/logos.mjs;public/js/lib/company-logo.js。

[1.103.0] — 2026-07-06

設定:「AI CLI 工具」——已安裝哪些。 career-ops 以 Claude Code 驅動,但可與任何遵循開放技能標準的代理 CLI 搭配。應用設定(#/config)中的新AI CLI 工具分頁顯示 Claude Code、Codex、Gemini CLI、OpenCode、GitHub Copilot CLI、Qwen、Antigravity 中哪些安裝在執行伺服器的機器上及其路徑。這是唯讀的 PATH 掃描:只檢查每個二進位是否存在,絕不執行它(無 --version,不執行),不寫入任何內容,也不觸碰使用者資料。

  • 新路由模組(第 28 個) server/lib/routes/cli-detect.mjs — GET /api/cli-detect。偵測從固定的 7 項白名單出發,沿 process.env.PATH 解析二進位路徑(Windows 的 .cmd/.exe/.bat 墊片;POSIX 的可執行位元);PATH 上的惡意檔案絕不會被此路由執行。
  • public/js/views/config.js 中的新「AI CLI 工具」分頁(延遲載入,可透過 #/config?tab=cli 深連結)。測試:tests/cli-detect-routes.test.mjs。新增 8 個 i18n 鍵 ×16(cli.* + config.tabCli)。說明 §2 就地擴充。

新增:server/lib/routes/cli-detect.mjs。

[1.102.0] — 2026-07-05

「向文件提問」——基於應用內說明指南的對話。 新增向文件提問 💬頁面(側邊欄,說明下方):輸入「如何掃描徵才入口?」這類問題,即可獲得僅來自你所用語言的應用說明指南的答案——它會顯示所用章節,且絕不讀取你的履歷、檔案或求職資訊。這是關於如何使用應用,而非關於你。有 LLM 金鑰時即時作答;無金鑰時提供一個已填入相關說明章節的現成提示詞。

  • 新路由模組(第 27 個) server/lib/routes/docs-assistant.mjs — POST /api/docs-assistant/ask。零相依檢索: 將你語言的說明文件拆分為 ## 章節,按與問題的關鍵字重疊評分;置頂章節被內聯,模型須據此作答或說明指南未涵蓋(不杜撰功能/路由)。共享供應商級聯、手動回退、限速、不寫入、不讀取使用者資料。
  • 新檢視 public/js/views/docs-assistant.js。測試:tests/docs-assistant-routes.test.mjs。新增 14 個 i18n 鍵 ×16(docs.* + nav.docsAssistant)。說明 §1 就地擴充。

新增:server/lib/routes/docs-assistant.mjs;public/js/views/docs-assistant.js。

[1.101.0] — 2026-07-05

CV Studio:針對特定職缺客製履歷並撰寫求職信——由招募人員檢查清單把關。 #/cv-studio 新增針對職缺客製卡片:貼上職缺描述(可選填目標職位/標題),CV Studio 即產生為該職缺客製的履歷以及相符的求職信,並在交付前讓兩者通過檢查清單關卡——error 攔截(在你看到結果前已修正),warn 提示。此機制把職涯輔導實務提煉為通用規則——招募人員幾秒內讀完,因此相關經驗置頂、標題符合職缺角色、成果帶具體數字、求職信保持簡短且只含一條「要求↔你相符的事實」的橋接。僅根據你自己的履歷、檔案和兩頁紙,絕不杜撰——不硬編碼公司、角色或經歷。

  • 新端點 POST /api/cv-studio/tailor(擴充現有 cv-studio 模組——沒有第 27 個模組):buildTailorPrompt + 通用 TAILOR_INSTRUCTIONS 關卡,基於 bundleProjectContext,共享供應商級聯,無金鑰時手動提示詞,限速,不寫入。結果透過共享 report-export.js 工具列匯出為 Markdown / PDF / DOCX。
  • 測試:tests/cv-studio-routes.test.mjs +3。新增 10 個 i18n 鍵 ×16(cvs.tailor*)。通用參考 docs/prompts/resume-cover.md。說明 §24 就地擴充。

新增:docs/prompts/resume-cover.md。

[1.100.0] — 2026-07-05

兩頁紙:基於履歷的 AI 自動填入 + 預覽 + 匯出為 PDF/DOCX/Markdown。 兩頁紙(#/two-pager)記錄你對下一份工作真正想要的東西,但先前每個欄位都得手動撰寫,或把提示詞複製到別的工具裡。現在**✨ AI 填入助手會用你設定的供應商即時執行——只讀取你的履歷 + 檔案(透過 bundleProjectContext,絕不杜撰),起草所有欄位(我是誰 / 喜歡 / 必備 / 討厭 / 硬性排除 / 不可妥協 / 目標環境)並填入表單,供你檢查、編輯並儲存。沒有 API 金鑰時,會像以前一樣回退到複製提示詞的彈窗。新的👁 預覽並匯出按鈕把兩頁紙渲染為帶格式的文件,並提供下載 .md / 另存為 PDF / 另存為 DOCX / 複製**工具列。

  • 零相依 .docx 匯出。 新增 server/lib/docx.mjs,產生一個最小但有效的 Office Open XML .docx(四個 OOXML 部件的 DEFLATE ZIP,逐條 CRC-32)——不引入新的執行階段相依(相依仍為 express + js-yaml)。新路由 POST /api/export/docx(server/lib/routes/export.mjs,第 26 個路由模組;無狀態,限制 200 KB,不寫入 / 不呼叫 LLM / 不抓取 URL)。已接入共享的 public/js/lib/report-export.js,因此市場報告、職涯規劃與職涯定位報告也獲得 DOCX 匯出。
  • 即時自動填入使用共享的供應商級聯(runActiveProvider / providerAvailable);回傳的 YAML 會被解析並強制轉換回受限的兩頁紙結構(parseYamlFields + normalizeTwoPager)——丟棄未知鍵,陣列/字串設上限。保留手動模式。
  • 測試:tests/export-routes.test.mjs。新增 4 個 i18n 鍵 ×16(export.saveDocx、twoPager.preview、twoPager.aiFilling、twoPager.aiFilled)。

新增:server/lib/docx.mjs;server/lib/routes/export.mjs。

[1.99.0] — 2026-07-05

入口網站健康頁面(#/portals)。掃描器監看 portals.yml 中的一組公司;ATS slug 可能悄然失效,該雇主便從此後所有掃描中無聲消失。新的 Portals 頁面列出每個受監看的公司,點擊 Check portal health 時透過 DNS 釘選的 safeGet(防 SSRF)探測每個 careers_url 並標記失效者(404 = 被無聲丟棄)——唯讀。同時依審查加固 v1.98.0 的錯誤回報器:錯誤環形緩衝區現在會捕捉網路層 fetch 失敗,清理器會遮蔽無標籤的供應商金鑰。

新增: server/lib/routes/portals.mjs; public/js/views/portals.js.

[1.98.0] — 2026-07-05

應用程式內錯誤回報器(與父專案 web-v0.2.0 Web 端對齊)。通知抽屜中的 🐞 Report a bug 按鈕會收集一份遵循隱私底線的診斷快照——版本、你的畫面、瀏覽器、/api/health 檢查摘要,以及來自新的用戶端環形緩衝區的最近 20 條錯誤——外加一個確定性的去重指紋(co-web-<base36>),讓你審閱確切的 Markdown,然後開啟一個預先填好的 GitHub issue。不會自動送出;絕不攜帶你的履歷、檔案、回答、職缺 URL 或金鑰。新程式庫 logbuf.js + bug-report.js;11 個 i18n 鍵 ×16;tests/bug-report.test.mjs。

新增: public/js/lib/logbuf.js; public/js/lib/bug-report.js.

[1.97.1] — 2026-07-05

評審驅動的強化與文件一致性(v1.97.0 的後續)。 梳理 AI 評審記錄後浮現出若干真實修正:

  • fit-score.js(掃描 ◎ 適合度徽章)。 salaryFloor() 不再將低於年薪口徑的費率抬升為虛假的年薪下限——「at least 500 EUR/day」「$80/hr」「6000 monthly」現在回傳 null,而非一個 500k/80k 的一票否決項。國家比對現在以整詞進行(\b…\b),因此「Germany」不再比對到形容詞「German」(也不再讓「Nigerian」裡的「Nigeria」命中),從而不會觸發錯誤的「必須在別處」違規。tests/fit-score.test.mjs 新增 3 個測試。
  • 文件一致性。 現在每個在地化 README 都一致地標註 16 個 locales——Help 列的計數/清單(×13)與在地化章節內文 + 「把鍵加到所有 N 個檔案」提示(×8)先前仍停留在 v1.85 之前的計數(8/9)。應用程式內說明 §17 的轉接器計數已在全部 16 個語言包中更正為 46 個轉接器——41 個英語 + 5 個俄語。

除適合度徽章啟發式外無行為變更;無新增路由、鍵或 i18n 條目。

[1.97.0] — 2026-07-05

Dassault Systèmes 掃描器來源 + 三線並進的品質整頓。

  • 新增掃描來源 — Dassault Systèmes(與父層 career-ops 對齊,#1498)。 server/lib/sources/dassault.mjs + server/lib/portals/adapters/dassault.mjs 複刻了父專案零 token 的 Exalead「卡片搜尋」提供者(3ds.com/careers/jobs 背後的公開資料來源)。它是單一全域端點,因此透過提供者選擇(provider: dassault)或從 3ds.com 主機自動偵測,並以 redirect:'error' 將 SSRF 主機固定為 www.3ds.com。XML 在不使用 DOM 的情況下解析(依 <Hit> 建立 <Meta> 對應),城市/國家從在地化的類別字串中擷取,只有當職缺的公開 URL 位於 *.3ds.com 上時才保留。註冊表現在提供 46 個轉接器(41 個 EN + 5 個 RU);ALL_ADAPTERS 計數、已排序 id 以及 /api/scan/sources 的 EN 集合斷言從 40 → 41。測試套件 tests/sources-dassault.test.mjs(10 個案例)。
  • 移植父專案的健壯性修正。 Avature 解析器現在容忍兩種線上租戶標記變體(帶位置索引後綴的 article--result + 無類別名稱的 JobDetail 標題錨點,#1541);Get on Board 會防禦 0/負值的 published_at(不再出現錯誤的 1970 日期);SuccessFactors 會對最後一頁設上限,使其不會超出 MAX_JOBS(#1528)。
  • 伺服器稽核修正。 safe-fetch 在超出上限的回應上不再卡住——大小上限路徑現在直接兌現 promise,而非等待一個已銷毀的串流永遠不會發出的 'end' 事件(修正大頁面的 /api/pipeline/preview + 自動流水線抓取)。SSE stream.* 活動記錄再次可達(/api/stream/ 檢查移到了籠統的「跳過 GET」防護之上)。
  • SPA 稽核修正。 #/stats 分頁切換器可防禦非同步繪製競態——慢速分頁的結果不再會覆蓋使用者已切換到的較新分頁。mock interview 與人脈拓展的刪除確認現在會傳入正確的標題 + 內文(不再有內文為空的對話框)。
  • 翻譯修正。 修正未翻譯的字典值——烏克蘭語 config.modes*(Adaptive Framing / Exit Narrative / Location Policy)、俄語 eval.jdLbl(「Job Description」)、義大利語 dash.quick.contactoSub(「referral」→「segnalazione」)——以及在 ru/uk/ja/ko/zh-CN/zh-TW 的 CHANGELOG 中將英文 16 個 locales 的樣板文案在地化。

新增: server/lib/sources/dassault.mjs; server/lib/portals/adapters/dassault.mjs.

[1.96.0] — 2026-07-04

職業方向(Epic 27)。 全新的 #/orientation 頁面回答「哪些方向真正適合我?」——就像職業測評能給你的那種解讀,但不是靠問卷,而是從你自己的 CV 和檔案中推斷。點擊 生成畫像,模型會回傳你的 最契合的職業向量(八種原型——功能主義者、管理者、溝通者、專家、分析者、創新者、經理、創業者——中哪一種契合,並附上證據)、一種職業類型傾向、推薦職位、與 CV 相關聯的職業優勢、工作風格傾向,以及發展建議。這是 對你的 CV 讀起來如何的一種 AI 反思——而非心理測驗:它不會虛構成就,也絕不會把數值分數當作實測結果來回報。可匯出為 Markdown 或 PDF;不會向磁碟寫入任何內容。

  • 新增路由 server/lib/routes/orientation.mjs(第 24 個路由模組)—— POST /api/orientation/generate 透過共享的提供者級聯,從 CV+檔案+兩頁紙+記憶建構畫像提示詞,並提供可複製貼上的手動回退與 不寫入任何檔案。
  • 在 Growth 導覽分組下,複用 report-export.js 實現 Markdown/PDF/複製。
  • 測試:tests/orientation-routes.test.mjs(反思式表述 / 無捏造分數,以 CV/檔案為種子的手動模式)。7 個新 i18n 鍵 ×16 個語言環境,說明 §28 ×16。

新增:#/orientation;server/lib/routes/orientation.mjs。

[1.95.0] — 2026-07-04

職涯規劃(Epic 26)。 全新的 #/career-plan 頁面會把你的 CV 與檔案轉化為一份具體、個人化的發展規劃。選擇一個 週期(6/12/24 個月)與一個可選的 聚焦方向,模型 —— 讀取你的 CV、檔案、雙頁簡介與記憶筆記 —— 便會寫出起點快照、優勢/成長 SWOT、以 SMART / OKR / WOOP 形式呈現的目標、替代發展軌跡、硬技能/軟技能規劃、一份 逐月路線圖、進度追蹤方法、常見陷阱與支援性舉措。它從你的素材真正體現出的內容向前規劃,絕不虛構你的過往經歷。可就地編輯,儲存到使用者層(config/career-plan.md),並匯出為 Markdown 或 PDF。

  • 新增路由 server/lib/routes/career-plan.mjs(第 23 個路由模組)—— GET/PUT /api/career-plan(寫入 config/career-plan.md)+ POST /api/career-plan/generate(共享的供應商級聯、手動回退、不作虛構)。PATHS.careerPlan。
  • 複用共享的 report-export.js(v1.94.0)用於 Markdown/PDF/複製,並新增一個成長導覽分組。
  • 測試:tests/career-plan-routes.test.mjs(邊界處理、GET/PUT 往返、感知週期並以 CV/檔案預填的提示詞)。全部 16 個 locales 新增 20 個 i18n 鍵,說明文件 §27 ×16。

新增:#/career-plan;server/lib/routes/career-plan.mjs;PATHS.careerPlan。

[1.94.0] — 2026-07-04

統計功能,全面翻新(Epic 25)。 #/stats 頁面現在是一個三頁籤的統計版塊,配有真實圖表與多得多的資料。全新的市場報告頁籤會請模型針對你目標職務在你所選地區與貨幣下的薪資與勞動力市場進行分析 —— 執行摘要、依職級並含 P10/P25/P75/P90 百分位的薪資、頂尖雇主、熱門技能表、福利出現頻率、辦公室/混合/遠端的占比、12–24 個月的趨勢,以及談判指引。每一項數字都標註為來自模型知識的方向性估計,絕不以抓取資料的形式呈現。全新的我的管線頁籤會繪製你自己的追蹤器:評分分布、狀態漏斗、頂尖公司與職務、隨時間變化的申請量,以及轉換率。原有的目標職務檢視(依國家的職缺/薪資 + 已儲存快照的趨勢)移入第三個頁籤,現在帶有貨幣選擇器與依職務的刊登數概覽。

  • 匯出任意報告為 Markdown 或 PDF,或直接複製它 —— 透過共享的 report-export.js 輔助工具實作(Markdown 以 blob 下載;PDF 透過既有的內嵌 PDF 執行器)。
  • 新增路由 server/lib/routes/market.mjs(第 22 個路由模組)—— POST /api/stats/market 會依據你的 CV/檔案(因此它知道你的目標職務)、地區與貨幣建構一段市場分析提示詞,透過共享的供應商級聯執行,並在沒有金鑰時回退為一段可複製貼上的提示詞。不寫入任何檔案。
  • 測試:tests/market-routes.test.mjs(地區/貨幣邊界、誠實標註的提示詞、以 CV/檔案預填的手動模式)。全部 16 個 locales 新增 36 個 i18n 鍵,說明文件 §26 ×16。

新增:#/stats 重構為頁籤;server/lib/routes/market.mjs;public/js/lib/report-export.js。

[1.93.0] — 2026-07-04

記憶層(Epic 24)。 全新的 #/memory 頁面存放一則簡短、可編輯的「關於我要記住的事」筆記,助手在每一項任務中都會將其納入考量:

  • 一則筆記,處處生效 — 由於它會內嵌進 bundleProjectContext,這則筆記會自動抵達每一次 AI 請求(評估、模擬面試、人脈拓展、CV Studio),橫跨所有供應商。寫一次;它就能引導一切。
  • 引導,而非事實 — 它捕捉的是你的偏好與你偏好的工作方式(語調、格式、不可退讓的底線、節奏),絕不包含關於你經歷的新事實聲明 —— 那些仍只存放在你的履歷、檔案與 two-pager 中。儲存於使用者層的 config/memory.md,絕不會被更新覆寫。
  • 從你的資料提出建議 — POST /api/memory/suggest 會從你自己的求職追蹤器中挖掘行為模式,並草擬條目供你審閱與編輯。它會讀取你的追蹤器;它絕不捏造事實,也不會發出任何即時呼叫。

新增:server/lib/routes/memory.mjs(第 21 個路由模組 —— GET/PUT /api/memory + POST /api/memory/suggest)、public/js/views/memory.js、PATHS.memory,以及新增至 bundleProjectContext 的 config/memory.md 區塊。全部 16 個 locales 新增 11 個 i18n 鍵。測試:tests/memory-routes.test.mjs。

[1.92.0] — 2026-07-04

CV Studio(Epic 21)。 全新的 #/cv-studio 頁面為你的履歷提供三項誠實、且多在本機運行的工具:

  • 履歷診斷 — 一個確定性的 0–100 分數,並附各項檢查的逐一說明(量化影響、無力的動詞、行話術語、篇幅、核心區塊、聯絡資訊)。純用戶端(window.CvDiagnostics)—— 不使用 LLM,絕不捏造,每一項發現都有解釋,由你決定要更動什麼。
  • 隱私遮罩 — 在把履歷作為範本或截圖分享之前,先遮蔽 PII(電子郵件、電話、連結/帳號、街道地址,並可選擇性地將你的姓名 → 縮寫)。完全在瀏覽器中執行(window.CvPrivacy);它會準確回報遮蔽了哪些內容,且絕不儲存原始資料。
  • 讓文字更像人味 / 語調匹配 — 貼上一句生硬的句子或段落,並以你的語調重寫,於伺服器端以 voice-dna.md 和 writing-samples/ 為依據。硬性護欄:它可以重新排序、精簡並重新賦予語調,但絕不引入文中尚未存在的事實、指標或成就。可透過共享的供應商級聯即時執行,或在沒有金鑰時回傳一段可複製貼上的提示詞。

新增:server/lib/routes/cv-studio.mjs(第 20 個路由模組 —— POST /api/cv-studio/humanize)、public/js/views/cv-studio.js、public/js/lib/cv-diagnostics.js、public/js/lib/cv-privacy.js、PATHS.voiceDna + PATHS.writingSamplesDir。全部 16 個 locales 新增 29 個 i18n 鍵。測試:tests/cv-diagnostics.test.mjs、tests/cv-studio-routes.test.mjs。(範本庫、Word 匯出與刊登 PDF 封存皆列為 CV Studio 的後續工作。)

[1.91.0] — 2026-07-04

人脈拓展與深度公司研究(Epic 16)。 全新的 #/networking 頁面將一家公司轉化為一份爭取面試的可執行計畫,並以你的履歷、檔案與 two-pager 為依據:

  • 公司檔案 — 一份精煉的簡報,說明公司做什麼、值得引用的近期動態,以及從你真實背景中提煉出的「我為何契合」的切入點。
  • 該聯繫誰 — 3–5 個目標人物誌(招募經理、內部招募人員、團隊中的資深 IC、一位有溫度的/校友人脈),並為每一位提供具體的 LinkedIn 搜尋字串。絕不捏造真實姓名。
  • 最溫暖的引薦路徑 — 針對你的背景最實際的溫暖切入路徑(共同的雇主/學校/社群、二度人脈路徑,或一則訊號強烈的冷啟動私訊)及其原因。
  • 觸達草稿 — 面向頭部人物誌的簡短、具體訊息,以你真實的佐證要點為依據。
  • 即時或手動 — 使用任意金鑰透過共享的供應商級聯即時執行,或回傳一段可複製貼上的提示詞(誠實回退,絕不臆造)。儲存計畫會將完成的計畫持久化到使用者層(networking/net-{company}-{role}-{date}.md);該頁面可列出、開啟並刪除已儲存的計畫。

新增:server/lib/routes/networking.mjs(第 19 個路由模組)、public/js/views/networking.js、PATHS.networkingDir。重用 v1.90.0 的 server/lib/llm-dispatch.mjs 級聯。16 個 locales 全部新增 24 個 i18n 鍵。測試:tests/networking-routes.test.mjs。

[1.90.0] — 2026-07-04

Mock Interview 2.0(Epic 15)。 全新的 #/mock-interview 頁面將你的履歷、檔案、two-pager 與故事庫變成逐輪進行的面試演練:

  • 對話式練習 — 設定一個目標職位(可選填公司 / JD),面試官會以一個聚焦的問題開場。你送出的每個回答都會得到結構化的回覆:Feedback(優勢 + STAR+R 缺口)、Score(N/5),以及一個探究你上一個回答最薄弱之處的 Next question。在伺服器端以你的真實素材為依據 —— 絕不捏造你沒有的經歷。
  • 感知故事庫 — interview-prep/story-bank.md 會內嵌進提示詞(與 cv.md 同等信任等級),因此回饋能指引你運用自己最好的故事。
  • 即時或手動 — 有供應商金鑰時,該輪次會透過共享供應商級聯(Anthropic → Gemini → OpenAI → Qwen → OpenRouter → GitHub Models)即時執行;沒有金鑰時,你會得到一個可直接複製貼上執行的提示詞(誠實回退,不捏造答案)。
  • 已儲存的工作階段 — 點擊 Save transcript 可將一場完成的面試持久化到使用者層(interview-prep/mock-{company}-{role}-{date}.md);該頁面可列出、開啟並刪除已儲存的工作階段。

新增: server/lib/routes/interview.mjs(第 18 個路由模組)、public/js/views/mock-interview.js、server/lib/llm-dispatch.mjs(共享供應商級聯)、PATHS.storyBank、bundleProjectContext({ extraFiles })。在全部 16 種語言 中新增 30 個 i18n 鍵。測試: tests/interview-routes.test.mjs。

[1.89.0] — 2026-07-04

候選人與市場契合 —— two-pager(Epic 14)。 新增的 #/two-pager 頁面讓你記錄 你自己 對下一份工作真正想要的東西,借鑑自 Never Search Alone 中的「Mnookin two-pager」:

  • 引導式建構器 —— 第一人稱「我是誰」敘述、「目標環境」備註,以及五個 chip 清單編輯器:loves、must-haves、hates、deal-breakers 與 non-negotiables。透過 PUT /api/two-pager 儲存到父專案的 使用者層(config/two-pager.yml)—— 絕不會被系統更新覆寫。
  • AI 填充助手(POST /api/two-pager/draft)—— 產生一個內聯了你的 CV + 檔案、可直接執行的 Mnookin 提示詞,供你在任意 LLM 中執行並把結果貼回來。它只使用你自己的素材;絕不捏造。
  • 與你所想的契合徽章 —— #/scan 上的每個職缺現在都顯示一個 ◎ N 契合分(用戶端,經由 window.FitScore),將職缺的工作型態、國家、最低薪資與搬遷跟你的 two-pager 進行比對。設計上誠實:當職缺沒有可比對的訊號時,不顯示徽章(絕不捏造數字)。deal-breaker 的違背比輕度的不喜歡權重更高。
  • 餵入每一次評估 —— 儲存的 two-pager 會被內聯進 bundleProjectContext,因此所有下游 LLM 評估都會將你陳述的偏好與 CV-對-JD 的比對結合起來。

新增:server/lib/routes/two-pager.mjs、public/js/views/two-pager.js、public/js/lib/fit-score.js、PATHS.twoPager。全部 16 個語言環境新增 27 個 i18n 鍵。測試:tests/two-pager-routes.test.mjs、tests/fit-score.test.mjs。

[1.88.0] — 2026-07-04

Issue #29 收尾 —— 掃描 i18n 缺口 + API 衛生。

  • 在地化最後殘留的硬編碼掃描字串(路線圖 v1.69.4):來源彙整標籤(N 個新增 / M 個相符)、N 個新職缺 提示以及 reloc 徽章現在皆透過 t() 流轉 —— 全部 16 個語言環境新增 4 個鍵(scan.pillNew、scan.pillMatching、scan.newOffers、scan.relocBadge)。非英語使用者不再於核心掃描流程中看到零散的英文。
  • 停用 X-Powered-By 回應標頭(路線圖 v1.69.5):createApp() 中的 app.disable('x-powered-by') —— 伺服器不再對外宣告使用 Express。(該主線的其餘部分先前已交付:parentVersion 去除其 release-please 註解、亮色模式主題切換、切換路由時關閉互動視窗,以及報告頁「Score」(rep.score)的在地化。)

測試:tests/scan-i18n-gaps.test.mjs + tests/security-headers.test.mjs 中的 X-Powered-By 缺失斷言。

[1.87.0] — 2026-07-04

4 個新增的免驗證掃描來源(與父專案 career-ops v1.16.0 對齊)。 掃描器註冊表從 41 → 45 個轉接器(40 EN + 5 RU)—— 全部為公開、免驗證、主機鎖定、redirect:'error'(SSRF 安全),且各自附一套 CI 隔離測試:

  • Get on Board(getonbrd)—— 全站公開 JSON:API(LATAM/遠端技術職缺),依來源選擇,支援分頁。server/lib/sources/getonbrd.mjs。
  • Amazon(amazon)—— amazon.jobs 公開搜尋 JSON,依主機偵測或 provider: amazon,依位移分頁。server/lib/sources/amazon.mjs。
  • Avature(avature)—— 依租戶的 *.avature.net ATS,解析 HTML,依主機偵測或 provider: avature。server/lib/sources/avature.mjs。
  • SAP SuccessFactors(successfactors)—— 依租戶的 RMK 磚塊列表(*.successfactors.eu/.com、jobs2web.com),解析 HTML。server/lib/sources/successfactors.mjs。

每個來源都提供一個 sources/<slug>.mjs(自動探索的 meta → #/scan 下拉選單)以及 ALL_ADAPTERS 中的一個 portals/adapters/<slug>.mjs(雙註冊表規則)+ tests/sources-<slug>.test.mjs。ALL_ADAPTERS 計數以及排序 id 與 /api/scan/sources EN 集斷言從 36→40;GET /api/scan/sources 現在列出 45 個。

[1.86.0] — 2026-07-03

依目標職位統計(#/stats)—— 針對你的目標職位的市場職缺與薪資統計。 新增的分析頁面讀取你的個人檔案中的目標職位(config/profile.yml → 非硬編碼)以及最近一次掃描的職缺,然後依職位與國家顯示:

  • 各國職缺數與各國薪資中位數(USD) —— 於用戶端從掃描器已收集的稀疏資料彙整而成(public/js/lib/role-stats.js,重用 window.Countries)。任意幣別的薪資透過一個明確標註為近似值的 FX 匯率表正規化為 USD,並附上樣本數提醒 —— 絕不捏造。
  • 職位與國家篩選器以及手寫的內嵌 SVG 長條圖與趨勢圖(無新增相依套件,CSP 安全 —— 僅使用 addEventListener)。
  • 儲存快照(POST /api/stats/snapshot)將目前的彙整結果持久化至 data/role-stats.jsonl;趨勢圖(GET /api/stats/trend)追蹤職缺數隨時間的變化 —— 即「動態」檢視。誠實的混合方案:快照來自本機掃描資料,依需求重新整理。
  • 已在全部 16 個語言環境中完整在地化(26 個新增 i18n 鍵)。

新增:server/lib/routes/stats.mjs(第 16 個路由模組)、public/js/lib/role-stats.js、public/js/views/stats.js、PATHS.roleStats;測試 role-stats.test.mjs(7)+ stats-routes.test.mjs(5)。

[1.85.0] — 2026-07-03

德語、義大利語和土耳其語語言環境(與父層 career-ops v1.16.0 語言環境對齊)。 介面現在提供 16 種語言 —— de 🇩🇪、it 🇮🇹 和 tr 🇹🇷 加入既有的 13 種。

  • 完整介面翻譯 —— 全部 730 個 i18n 鍵皆在 public/js/lib/locales/i18n-dict.{de,it,tr}.js 中翻譯;語言切換器列出 Deutsch / Italiano / Türkçe,瀏覽器語言自動偵測可辨識 de/it/tr(public/js/lib/i18n.js)。
  • 應用程式內說明指南 —— docs/help/{de,it,tr}.md 已翻譯(完整的 19 個 H2 / 75 個 H3 結構),由 GET /api/help/:lang 提供。
  • 文件 —— 新增 README.{de,it,tr}.md 和 CHANGELOG.{de,it,tr}.md;CHANGELOG 語言環境對齊檢查現在涵蓋 15 個非 EN 語言環境。
  • 提示鷹架 —— server/lib/prompts.mjs(LOCALE_NAMES + SCAFFOLD_STRINGS)已針對三個新語言環境在地化,使 LLM 輸出遵循介面語言。

所有對齊檢查(i18n-locale-files、i18n-coverage、check-changelog-parity、lang-switcher-rtl)皆擴展至 16 個語言環境集合。

[1.84.0] — 2026-06-30

重新申請冷卻 + pipeline.md 中的薪酬欄位(與父層 career-ops v1.15.0 對齊)。 兩項掃描器升級:

  • 重新申請冷卻(#1201):EN 掃描現在會略過你近期已投遞過的公司職缺,讓結果聚焦於全新機會。在 config/profile.yml 的 re_apply_windows: 下按公司設定冷卻視窗(last_apply_date、same_role_days、applied_to: [roles],選填 cross_role_bucket);公司比對採去標點 + 詞界模糊比對(server/lib/cooldown.mjs)。未設定該鍵時自動停用;掃描日誌顯示 Cooldown skipped: N。
  • pipeline.md 中的薪酬欄位(#1017):掃描到的職缺現在會以選填尾欄(url | <salary>)的形式將薪資持久化至 data/pipeline.md。URL 仍為去重鍵(讀取時會剝除 | comp 欄位),儲存格已做清理(無列/欄注入,以公式起始的內容會被中和),純 URL 格式的 pipeline 維持向下相容。

隨附 tests/cooldown.test.mjs 及 pipeline 薪酬測試。來源總數維持 41(兩項均為掃描邏輯升級,並非新看板)。

[1.83.0] — 2026-06-30

重複刊登 / 幽靈職缺偵測器(與父層 career-ops v1.15.0 對齊)。 #/scan 頁面新增 🔁 重複刊登 / 幽靈職缺 面板,標記同一公司+職位組合在 90 天滾動視窗內以不同 URL 重複刊登的情形——此為招募管線停滯與幽靈職缺的信號。底層由模糊職稱比對器(server/lib/role-matcher.mjs)和針對 data/scan-history.tsv 的唯讀偵測器(server/lib/detect-reposts.mjs)支援,透過 GET /api/scan/reposts 公開。另:/api/health 的 parentVersion 現在僅回傳語意化版本號(已去除 release-please 的 # x-release-please-version 註解)。隨附 tests/detect-reposts.test.mjs。來源總數維持 41——重複刊登為分析功能,並非新看板。

[1.82.0] — 2026-06-30

NoDesk 掃描來源(與父層 career-ops v1.15.0 對齊)。 全站 NoDesk 遠端職缺 RSS 來源現已成為一級掃描來源——加入 provider: nodesk 條目後即出現在 #/scan 的 Source 下拉中(共 41 個轉接器:36 EN + 5 RU)。主機鎖定為 nodesk.co 並使用 redirect:'error'(防 SSRF);標題以 Role at Company 拆分(NoDesk 無地點標籤,地點欄位留空);所有職缺標記為遠端。隨附 CI 隔離的 tests/sources-nodesk.test.mjs 測試套件;完整單元測試套件綠燈,共 1523 個。

[1.81.0] — 2026-06-29

與父層 career-ops 對齊 — 13 個全新職缺看板掃描來源。 將 Fighter90/career-ops main 的最新提供者批次移植至 in-process 掃描器。全站公開 API(provider 選擇):Arbeitnow、Himalayas、Jobicy、Landing.jobs、4 Day Week、The Muse、The Hub、Jobspresso(RSS),以及 Hacker News “Who is hiring?”(Algolia 兩步驟)。波蘭看板(主機或 provider: 偵測):JustJoin.it 和 NoFluffJobs(POST 搜尋)。按租戶 ATS(從 careers_url 自動辨識):Pinpoint(<slug>.pinpointhq.com/postings.json)和 Rippling(ats.rippling.com/<slug> → api.rippling.com board)。每個來源均以 redirect:'error' 鎖定主機(防 SSRF),並可在 #/scan 的 Source 下拉中選取 —— 註冊表現已提供 40 個掃描器轉接器(35 EN + 5 RU)。新增 13 個 CI 隔離的逐來源測試套件;完整單元測試套件綠燈,共 1513 個。

[1.80.0] — 2026-06-28

五項掃描升級(源自 job-crawler 的想法,已重新實作)。 (1) Teamtailor 來源——透過其公開 /jobs.rss 來源抓取 <slug>.teamtailor.com 的按租戶站點,從 careers_url 自動辨識(主機鎖定 + redirect:'error');註冊表現有 27 個轉接器。(2) 來源隔離——回傳永久 404/410 的來源會寫入 data/scan-quarantine.json 並在後續掃描中略過(自我修復:14 天後重試)。(3) 每來源上限——#/scan 上的選用欄位,限制每個 board 的職缺數(預設 ∞)。(4) 發佈時間——用戶端的時效篩選(24 小時 / 7 天 / 30 天)。(5) 已儲存搜尋 + ★ 收藏——為篩選組合命名並重用、為職缺加星;儲存在 localStorage 並具防禦性驗證(損壞的快取會乾淨重設);結果快取在每次掃描前重設並即時回填。

[1.79.0] — 2026-06-28

WeWorkRemotely 掃描來源(與上游 career-ops v1.14.0 對齊)。 We Work Remotely 全站遠端職缺 RSS 來源現已成為一級掃描來源——加入 provider: weworkremotely 條目後即出現在 #/scan 的 Source 下拉中(共 26 個轉接器)。主機鎖定為 weworkremotely.com 並使用 redirect:'error'(防 SSRF);標題以 Company: Role 拆分。此外,title_filter 關鍵字現在會在長度檢查之前修剪(parent #1261)。

[1.78.2] — 2026-06-27

i18n 與 UX 強化(v1.78.1 的後續修復)。 品牌 Logo 的無障礙名稱現已在全部 13 種語言在地化(nav.logoHome)。在已位於 #/scan 時按全域搜尋 Enter 會強制重新渲染,避免遺失預填關鍵字(同路由守衛)。health.title 現已翻譯為波蘭語(Kondycja)與丹麥語(Systemtilstand)——先前為英文。測試 1235 → 1238。

[1.78.1] — 2026-06-27

Scan 體驗修復。 #/scan 結果表現在會在掃描期間即時自動重新整理,並在結束後再刷新一次,無需手動重新載入。頂列全域搜尋顯示 Enter 提示;對於非 URL 查詢,會跳轉到 #/scan 並預先填入搜尋框(先前為 #/tracker)。Logo 現在連結到儀表板(首頁)。

[1.78.0] — 2026-06-27

Scan 頁面新增地理篩選 —— 依國家篩選職缺(帶國旗)。 #/scan 中新的 國家 下拉選單列出在結果中辨識到的每個國家(國旗表情 + 數量),可僅保留與特定國家相關的職缺 —— 與 Remote/Hybrid/Onsite 工作方式篩選並用,既能找綁定國家的工作,也能找遠端。由新的 countries.js 輔助程式支援,將職缺的自由文字地點(國家名、別名及約 100 個主要城市)對應到 ISO 國家 + 國旗;辨識保守,絕不臆測。

[1.77.0] — 2026-06-27

新增丹麥語(Dansk)作為第 13 種介面語言。 完整翻譯 UI、應用內說明指南(19 H2 / 75 H3)、README 與 CHANGELOG。丹麥語加入帶國旗的語言選擇器;i18n 機制(組譯器、稽核、對等檢查、快照)現已涵蓋 13 個語言環境。

[1.76.0] — 2026-06-26

與上游 career-ops v1.13.0 對齊 —— 新增 6 個職缺來源、強化掃描器、結果表取消上限。

新增

  • 6 個按租戶的 ATS 來源 —— BambooHR、Breezy HR、Comeet、Personio、Recruitee、SolidJobs。從 careers_url 主機自動辨識(Comeet 需完整 api:);每個主機以錨定正規表示式 + redirect:'error' 鎖定(防 SSRF)。可在 #/scan 的 Source 下拉選單中選擇 —— 註冊表現有 25 個轉接器(EN 20 + RU 5)。為 Personio 的 XML 來源新增 fetchText 輔助函式。
  • trust_filter —— 選用的信任評分(0–100,等級 high/medium/low,旗標),僅標註。低於 high 的列在 #/scan 顯示語言中立的 ⚠ 徽章;絕不丟棄職缺。
  • Arbeitsagentur remoteMatch + remoteMaxPages —— 由設定驅動的遠端辨識:title、filter(伺服器端 homeoffice=nv_true + 分頁)或 off。

變更

  • 掃描結果不再設上限。 移除顯示上限 MAX_STORED_RESULTS(2000)—— 儲存所有相符項,#/scan 表格分頁顯示(200/頁)。
  • 標題篩選更穩健 —— 短縮寫(COO、SDR…)依詞界比對;格式錯誤的 title_filter 不再使掃描崩潰。ATS 與區域掃描器皆適用。

測試

  • +32 案例(1190 → 1222):sources-ats-providers、title-filter、arbeitsagentur-remote、trust-validator,以及重寫的 scan-result-cap「無上限」守衛。

[1.75.2] — 2026-06-19

docs:在全部 12 個語言環境中為 v1.75.0 的掃描器彙整器提供完整的文件對等。 無程式碼改動 — 將面向使用者的文件與 v1.75.0 中落地的七個來源對齊:

  • 說明指南(12 個語言環境)。 §5 新增一個 content_filter 區塊(依描述/摘要關鍵字門控,是 location_filter 的同類項)以及一則關於彙整器的說明;§7 在一鍵掃描的巡覽與完整的 Source 下拉列舉中列出這七個新來源;§17 的轉接器計數從過時的 “11 adapters” 更正為 “19 adapters — 14 English + 5 Russian”。沒有新增 ##/### 標題,因此受門控的 19 H2 / 75 H3 結構保持不變。
  • README(9 個完整語言環境)。 在掃描來源下新增 “Aggregator boards (v1.75.0)” 條目,並將發布徽章提升至 v1.75.2。(精簡版的 pl/uk/ar README 沒有依來源的清單,該處刻意不作改動。)
  • 參考文件。 docs/portals-examples.md 新增一個可複製貼上的 “Aggregator boards” 章節,為這七個來源提供準確的 provider: / <provider>: 設定區塊;docs/PROJECT.md 更新為 19 adapters;docs/sdd/CONVENTIONS.md 記錄了兩個註冊表的區分(用於下拉的 sources/registry.mjs 對用於抓取的 portals/registry.mjs)、以 opts.company 形式傳遞的基於 provider: 的彙整器選擇、掃描寫入清理器(scan-sanitize.mjs)以及 v1.75.1 的測試數量(1190)。
  • QA。 新增 qa/QA-REGRESSION-PROMPT-v1.75.2-FULL.md — 全表面發布閘驅動器,已為 v1.75.x 掃描彙整器週期翻新。

[1.75.1] — 2026-06-19

fix(scan): 對 v1.75.0 組態驅動來源的健全性打磨。 來自發布後檢討的三處小型強化修正(正常掃描下行為不變):

  • 支援中止的分頁延遲。 Glints(300 ms)與 Jobstreet/SEEK(200 ms)的翻頁禮貌等待現在會在掃描的 AbortSignal 觸發時立即結束,這透過 server/lib/http-json.mjs 中新增的 delay(ms, signal) 輔助函式實現,因此已斷線的用戶端無法讓一個正在分頁的掃描多佔用一段等待時間。
  • 描述性的非 JSON 錯誤。 fetchJson 現在會將非 JSON 的 2xx 回應主體(例如以狀態碼 200 回傳的 HTML 維護頁)包裝為 non-JSON 2xx response from <url>,而非暴露一個裸的 SyntaxError,因此掃描器依來源記錄的錯誤日誌會指明行為異常的端點。
  • 更強的掃描寫入正規化。 normalizeScanScalar 現在除了 \r \n \t 之外,還會折疊垂直定位字元、換頁字元以及 Unicode 行/段分隔符(\v \f U+2028 U+2029)——這是一個嚴格的超集,因此任何試算表或檢視器可能辨識的記錄/行分隔符都不會殘留進 scan-history.tsv。

[1.75.0] — 2026-06-19

feat(scan):移植父層 career-ops v1.12.0 — 七個新的職缺來源、內容過濾以及安全/品質修正。 web-ui 執行自己的程序內掃描器(不會向父層的 scan.mjs 進行 shell out),因此父層 v1.12.0 的提供者與掃描變更不會自動流入 — 本次發布將其中適用的部分按 web-ui 的轉接器契約重新實作。

  • 七個新的掃描器來源。 三個涵蓋整個職缺板的遠端彙整器 — RemoteOK、Remotive、Working Nomads — 接入自動探索的 server/lib/sources/*.mjs 模式(以 provider: remoteok / remotive / workingnomads 選擇)。四個由設定驅動的區域彙整器 — IBM careers、Arbeitsagentur(德國聯邦勞動局)、Glints(東南亞)、Jobstreet / SEEK — 讀取依條目的 <provider>: 設定區塊;en-scanner 現在會將解析後的公司條目一路傳遞到每個 fetcher,以便它們能夠讀取。這七個來源都會自動出現在 #/scan 的來源下拉選單中。
  • content_filter(父層 #974)。 可選的 portals.yml 區塊(positive / negative 關鍵字清單),依職缺的描述/摘要文字對其進行門控 — 沿用 location_filter 的語意;沒有描述的職缺一律通過。已接入 EN 與 RU 兩個掃描器。
  • 掃描寫入強化(父層 #1098)。 外部資訊來源的中繼資料現在會在落入 data/scan-history.tsv 與 data/pipeline.md 之前進行清理:控制字元會被摺疊(公司名/職稱中的換行不再能注入一列 TSV),開頭的 = + - @ 會被中和以防試算表公式注入。
  • Ashby secondaryLocations(父層 #1073)。 Ashby 來源現在會將每個次要地點的地區標籤連同郵政 addressLocality / addressCountry 摺疊進地點字串(去重),因此主標籤顯示為例如 “Canada” 的可在歐盟工作的職缺會被 location_filter 浮現出來。
  • 評估報告形狀驗證(父層 #819)。 /api/evaluate 的程序內提供者(Anthropic / OpenAI / Qwen / OpenRouter / GitHub Models)現在會將格式錯誤的 A–G / SCORE_SUMMARY 報告標記為非致命的 warnings 陣列;Gemini 評估路徑已從父層的 gemini-eval.mjs 繼承該防護。
  • docs: 在全部 12 個 README 的受支援助手清單中加入 Antigravity CLI(對應到 Gemini 提供者)。

從父層 git pull 免費繼承(web-ui 會向這些 shell out):日語 CJK PDF 字型回退(#1053)、ATS 安全的 PDF 字型(#1074)、LaTeX CJK 防護(#1054)、tracker/merge/followup/dashboard 修正,以及 modes/zh 中文模式(web-ui 會動態列出模式)。


[1.74.3] — 2026-06-18

docs(parent-source): 將父 career-ops 儲存庫指向 Fighter90/career-ops 分叉。 web-ui 現在在所有作為實際來源的位置都將維護者的分叉作為父專案引用:bin/setup.sh 安裝腳本的 CAREER_OPS_REPO clone 預設值、12 個 README 中的每個 git clone /「建構於其上」/ onboarding 連結,以及代理文件(CLAUDE.md、AGENTS.md、GEMINI.md、.github/copilot-instructions.md、docs/)。對作者 santifer 的署名(以及非官方 UI 免責聲明)保持不變 —— 僅移動了來源/clone URL。tests/sh-files.test.mjs 現在斷言安裝腳本 clone 的是分叉。


[1.74.2] — 2026-06-17

fix(health): 在 #/health 與 /api/status/providers 中將 GITHUB_MODELS_API_KEY 作為可選檢查項目呈現。 v1.74.0 的 GitHub Models 提供商可在 #/config 中設定,但在 Health 頁面上沒有對應列,且在 keysConfigured 提供商表面中缺失。新增了可選檢查項目(與其他五個線上評估提供商相同的 “set / unset (manual mode)” 措辭),並將 github(及其 GITHUB_MODELS_MODEL)新增至 /api/status/providers,因此活動提供商路由與 Health 頁面現在均反映全部六個。tests/api.test.mjs 的健康列測試已擴展到全部六個提供商。


[1.74.1] — 2026-06-17

docs + test: README「安裝 AI 助手」章節;Gemini 連接器的完整分支覆蓋。 在 README 中新增安裝/登入對照表——Claude Code / Gemini CLI / Codex / Qwen Code / OpenCode / GitHub Copilot CLI 的安裝連結 + 各自的 #/config 提供商對應 + 「繼續前請先登入」(與 career-ops.org/docs 快速入門保持一致;說明 web-ui 是無需 CLI 的獨立替代方案)。新增 tests/gemini-connector.test.mjs(8 個案例),涵蓋 runGemini 的每個分支——無金鑰、成功、API 錯誤、空/被封鎖的補全、格式錯誤的回應主體、逾時、網路錯誤、hasGeminiKey——使 server/lib/gemini.mjs 語句覆蓋率達到 100%。整體覆蓋率:96% 行 / 88% 分支 / 96% 函式。測試套件 1126 → 1134。


[1.74.0] — 2026-06-17

feat(llm): GitHub Models (Copilot) 作為第6個提供商 + 6個助手的規範對齊。 career-ops.org/docs 列出了六個AI程式設計助手 — Claude Code, Gemini CLI, Codex, Qwen Code, OpenCode, GitHub Copilot CLI。web-ui 現在支援全部六個:五個對應到現有的線上提供商(Anthropic / Gemini / OpenAI / Qwen / OpenRouter),GitHub Copilot CLI 獲得了專用的 GitHub Models 連接器 — runGitHubModels(OpenAI-compatible;具有 models 權限範圍的 GitHub PAT),可在 #/config 中設定(GITHUB_MODELS_API_KEY + GITHUB_MODELS_MODEL),並可透過 LLM_PROVIDER=github 選擇;在 auto 順序中排第6位。說明套件和 README 現在列出了規範的六個(將 Qwen CLI 重新命名為 Qwen Code;新增了 Gemini CLI + GitHub Copilot CLI),README 還新增了完整的模式參考和入口網站介面卡連結表,指向 career-ops.org/docs,使每個功能都可以追溯到父專案。tests/llm-provider-context.test.mjs 將擷取邊界矩陣擴展到所有六個提供商(cv.md + profile.yml 內嵌 + 傳回的構件);新的 GITHUB_MODELS_* 鍵已新增至所有 12 個語言區域字典中。測試套件 1125 → 1126。


[1.73.0] — 2026-06-17

feat(llm): 通用 Gemini 連接器 + 跨所有提供商驗證的履歷/設定檔上下文。 新增 server/lib/gemini.mjs(runGemini)——一個無外部依賴的 Gemini generateContent 客戶端,回傳與 Anthropic / OpenAI 相容客戶端相同的 {markdown, usage, error} 結構。修正:/api/mode/:slug 與 /api/deep 先前將提示詞路由至僅用於職缺評估的 gemini-eval.mjs,導致 Gemini Run live 回傳評估結果而非請求的產物(求職信、外聯信、簡報)。現在它們透過 bundleProjectContext 呼叫 runGemini,因此 cv.md + config/profile.yml 對 Gemini 的內嵌方式與其他所有提供商完全一致——信件和簡報更加詳盡且個人化。新增的 tests/llm-provider-context.test.mjs 模擬每個提供商的 HTTP 邊界,並驗證全部五個提供商(Anthropic / Gemini / OpenAI / Qwen / OpenRouter)均內嵌 cv.md + profile.yml 並回傳產物(mode + deep + evaluate 矩陣,9 個案例)。/api/evaluate 保留其針對職缺調優的 gemini-eval.mjs。Suite 1116 → 1125。


[1.72.0] — 2026-06-17

feat(modes): Run live 現在直接傳回最終產出物(單次執行輸出契約)。 父模板 modes/<slug>.md 是為 Claude Code 的互動式工作階段所撰寫的——其中幾個(cover、contacto 等)在產生結果前會暫停以詢問釐清問題,導致 Web UI 的 Run live 輸出問卷而非產出物。buildModePrompt 現在將每個模式包裹在非互動式輸出契約中:靜默執行分析(職缺說明拆解、公司備註、ATS 關鍵字、個人檔案↔職缺差距、語氣/角度選擇),從 cv.md / config/profile.yml 為模板通常會詢問的內容選取合理的預設值,並僅輸出最終產出物——以每種模式的「output ONLY {the cover letter / outreach message / …}」提示作為結尾。因此,在 #/cover 上點擊 Run live 現在將直接傳回求職信本身;相同的修正適用於所有通用模式(cover、contacto、interview-prep、project、training、followup、patterns)的全部 12 個語言環境(產出物透過語言環境指令以 UI 語言撰寫)。Suite 1103 → 1116。


[1.71.2] — 2026-06-17

docs(i18n): 發布文件一致性整理結果。每個 README 的 “Translations of this guide” 區塊現在列出了全部 11 種同級語言(此前部分語言遺漏了 English/Français 或存在自連結),並恢復了節分隔符前的空行。完整的 QA 回歸提示詞已重命名為目前版本,文件(CLAUDE.md、CONVENTIONS、LOCALIZATION、PROJECT-CONTEXT)已與目前版本和測試數量(1103)同步。無程式碼或行為變更——僅文件變更,因此說明/UI 翻譯及 1.70.0–1.71.1 中的所有功能均保持不變。


[1.71.1] — 2026-06-17

fix(i18n): 應用程式內的說明指南現已完整翻譯為全部 12 種語言。 新增 docs/help/{pl,uk,ar}.md(每個檔案均包含經過驗證的 19 H2 / 75 H3 結構),使 #/help 能夠為波蘭語、烏克蘭語和阿拉伯語提供原生語言包,而不再退回英語 — GET /api/help/{pl,uk,ar} 現在會回傳各自的語言區域內容。已串接至所有說明檢查項(help-ui、help.test、help-ru-config-section、canonical-docs-coverage)。同時完成了所有 12 種語言的翻譯清單:README 中的 «Translations of this guide» 區塊(9 個 README)、本地化 CHANGELOG 中的 «Translations:» 標題(8 個檔案),並更新了過時的文件計數。Suite 1100 → 1103。


[1.71.0] — 2026-06-16

feat(cover): 直接從 #/cover 產生求職信 PDF。 v1.70.0 新增的 cover 模式可產生信件內文;結果頁面現在提供 Generate PDF 按鈕,透過共用的內嵌 markdown→PDF 管線(POST /api/stream/pdf/inline → generate-pdf.mjs)進行渲染,與 interview-prep 使用的路徑相同。現在無需離開 SPA 即可撰寫信件並產生 PDF 傳送。

test/docs: v1.70.0 審查強化。 為 cover 模式(允許清單 + 提示詞組裝)、國旗 <select> 切換器 + 阿拉伯語 RTL(dirFor/<html dir>)、每個語言環境的 top.langLabel、求職信 PDF 連接,以及 prompts.mjs 語言環境指令 + fr/pl/uk/ar 鷹架新增了 CI 隔離覆蓋率。更新了 docs/sdd/CONVENTIONS.md 和完整專案 QA 迴歸提示中過時的「全部 8 個」→ 12 個語言環境參照。


[1.70.0] — 2026-06-16

feat(i18n): 新增三種 UI 語言——波蘭語(pl)、烏克蘭語(uk)和阿拉伯語(ar,含完整 RTL 支援)——將 SPA 擴展至 12 個語言區域,與父專案 career-ops README 中的所有語言保持一致。 每種新語言區域均附帶包含 697 個鍵的完整詞典(public/js/lib/locales/i18n-dict.{pl,uk,ar}.js),並通過現有的奇偶校驗 / 覆蓋率 / 無拉丁字母洩漏 / 無個人資料測試套件驗證。阿拉伯語新增真正的由右至左支援:i18n.js 為 RTL 語言區域設定 <html dir="rtl">,app.css 中有範圍的 [dir="rtl"] 區塊鏡像頁面外殼(側邊欄、通知抽屜、markdown 表格/區塊引用、行內間距)——LTR 語言區域的位元組內容完全不變。新增 top.langLabel 鍵(×12)為螢幕閱讀器命名語言選擇器。

feat(ui): 帶國旗圖示的 <select> 語言切換器取代了原本會換行的按鈕列。 有 12 個語言區域時,舊的 .lang-btn 列在側邊欄中會換行為三列;原生 <select>(每個選項以國旗 emoji 為前綴)能夠整潔地擴展,開箱即用地支援鍵盤和螢幕閱讀器,並且對 CSP 安全(透過 addEventListener 處理變更事件,無內嵌 JS)。在平台缺少國旗字形的情況下,國旗會降級為地區字母,因此語言標籤始終是關鍵識別符。

feat(cover): 將父專案的求職信模式(career-ops v1.10.0 + v1.11.0 問候語)移植到 SPA。 在「申請」導航群組下新增 #/cover 頁面,基於通用模式執行器建構:職位描述 + 公司/職位 + 可選問候語 → 從 cv.md / modes/_profile.md 生成的客製化求職信。將 cover 新增至伺服器 MODE_ALLOWLIST 和 cover.* i18n 區塊(×12 個語言區域)。

chore(compat): 追蹤父專案 career-ops v1.11.0。 已驗證讀寫契約完好無損——data/applications.md 仍是 markdown 真實資料來源(v1.11.0 SQLite 追蹤器索引是派生快取),追蹤器欄位仍按標題映射。parentVersion 現在回報 1.11.0。

fix(i18n): 修復了一個潛在缺陷,即法語(在 v1.61.0 中新增)缺失於 server/lib/prompts.mjs 的 LOCALE_NAMES 和 SCAFFOLD_STRINGS 中——法語 LLM 呼叫靜默回退至英語輸出和英語鷹架。fr/pl/uk/ar 現已全部接入提示語言區域路徑。

已知後續工作:應用程式內說明指南(docs/help/)對 pl/uk/ar 回退至英語(UI 外殼本身已完全在地化);父專案的互動式面試引導、反向 ATS 探索以及較新的掃描提供商尚未在 SPA 中呈現。


[1.69.2] — 2026-06-12

fix(test):修復一處測試隔離洩漏,此前 npm test 會覆寫你真實的 config/profile.yml 和 data/scan-history.tsv。 tests/critical-fixes.test.mjs 在檔案頂部匯入了 prompts.mjs(→ paths.mjs),導致在 before() 將 CAREER_OPS_ROOT 設為暫存目錄之前,PROJECT_ROOT 就解析到了真實的父目錄 —— 於是 PUT /api/profile 每次執行都會把「Acceptance Test」夾具寫入你的真實檔案。修復:在 before() 內透過動態 import() 載入 prompts.mjs。新增 tests/test-root-isolation.test.mjs(2 個案例)保護整個測試套件免受該模式影響。無正式環境程式碼變更。測試套件 1084 → 1086。


[1.69.1] — 2026-06-12

fix(scan):#/scan 不再靜默截斷大型區域掃描。 每個區域的顯示集被硬限制為 500 筆(真實的 RU 掃描有 1352 筆相符,卻只顯示 500 筆,隱藏 852 筆 —— 即「掃描 2000、僅顯示約 600」的症狀)。兩個掃描器現在使用共用且可經環境變數覆寫的常數 MAX_STORED_RESULTS(預設 2000,可透過 SCAN_MAX_RESULTS 覆寫)。僅影響顯示 —— 寫入 pipeline.md / scan-history.tsv 早已使用未截斷的集合。fix(health/ui):#/health 檢查卡片不再溢位。 過長的名稱/值會與 Fix → 按鈕和狀態徽章重疊;該列現在透過 .health-check-row 收縮並換行。新增測試 scan-result-cap + health-card-overflow。測試套件 1079 → 1084。


[1.69.0] — 2026-06-12

feat(scan):掃描器轉接器自動發現 (P-14)——只需在 server/lib/sources/ 中放入一個 .mjs 檔案即可註冊新資料源。 在 v1.69 之前,server/lib/sources/registry.mjs 中的資料源清單是手動維護的靜態陣列:新增轉接器需要同時修改 <id>.mjs 和 registry.mjs。完成路線圖項目 P-14(docs/ROADMAP.md)的剩餘部分。現在 server/lib/sources/ 中的每個 *.mjs 在模組啟動時動態載入,每個轉接器透過自描述區塊 export const meta = { value, label, region, configKey? } 宣告自身。已發布的 12 個轉接器(ashby / greenhouse / lever / rss / smartrecruiters / workable / workday + geekjob / getmatch / habr / hh / trudvsem)各自獲得 meta;registry.mjs 透過 top-level await 解析 readdirSync + 動態 import()(Node 18+ ESM 標準)。公開 API(SOURCES, SOURCES_BY_REGION, RU_CONFIG_KEYS, getRegionalSources)保持不變——所有現有匯入繼續運作。格式錯誤的 meta 會被拒絕,每個問題檔案都會輸出一次 console.warn。新增 tests/sources-registry-discovery.test.mjs,包含 14 個測試案例。套件 1065 → 1079。


[1.68.2] — 2026-06-07

fix(bin):透過 npx / npm link 呼叫的 CLI 動詞先前已損壞——現在 bin 路徑會沿符號連結解析。 npm 與 npx 會將 career-ops-ui 公開為 node_modules/.bin/ 下的符號連結,而舊的 dirname "${BASH_SOURCE[0]}" 指向的是 .bin 而非套件根目錄,於是 npx career-ops-ui init 會執行 node node_modules/scripts/init.mjs 並以 MODULE_NOT_FOUND 崩潰(本機 npm install 執行不受影響,因而掩蓋了該缺陷)。現在 bin/career-ops-ui.sh 與 bin/start.sh 會沿符號連結鏈正規化 SCRIPT_DIR(readlink 迴圈 + cd -P),因此每個動詞都能從儲存庫、透過 npm link 以及透過 npx 正常運作。在 tests/sh-files.test.mjs 中新增一個回歸鎖,透過 .bin 風格的符號連結執行動詞。套件 1065/1065。


[1.68.1] — 2026-05-29

fix(scan):各來源抓取逾時 10s → 60s。 v1.67.1 的 10s 快速失敗也會切掉只是需要更多時間的「緩慢但存活」的 Ashby 看板。把預設值提高到一分鐘,讓它們有機會回傳。權衡:真正死掉/掛起的來源現在會占用並行槽整整 60s(最壞情況掃描更慢),而長期掛起者(Perplexity、Supabase、Resend 等)很可能仍會逾時——要真正解決需按來源處理 / 降低 Ashby 並行。可用 SCAN_FETCH_TIMEOUT_MS 覆寫。套件 1063/1063。


[1.68.0] — 2026-05-29

feat(scan):重做結果篩選面板 —— 帶標籤的欄位、套用按鈕、現場辦公選項,以及真正生效的薪資篩選。 #/scan 的每個篩選現在都是帶標籤的欄位(標籤在控制項上方,而非佔位符):搜尋 · 工作類型 · 薪資下限 · 薪資上限 · 來源 · 範圍。明確的套用按鈕(外加重設,以及在任意欄位按 Enter)會重新執行篩選;頁面提示說明用法。薪資區間現在真正生效 —— 一旦設定下限/上限,薪酬超出區間的職缺以及未標註薪資的職缺都會被移除(區間重疊;忽略幣別)。工作類型篩選在 遠端 / 混合 / 搬遷 之外新增現場辦公選項。新增 i18n 鍵 ×9;salaryInRange 改為嚴格;套件 1063/1063。


[1.67.1] — 2026-05-29

fix(scan):各來源抓取逾時 30s → 10s(快速失敗)。 v1.67.0 提到 30s 只挽回約一半的緩慢 Ashby 看板;其餘(Perplexity、Supabase、Resend、DeepL、Ramp 等)無論期限都會掛起,因此更長的逾時只是讓整次掃描在等待死槽時停滯。10s 對長期掛起者快速失敗並保持掃描的回應性。可用 SCAN_FETCH_TIMEOUT_MS 覆寫。套件 1060/1060。


[1.67.0] — 2026-05-29

feat(scan):#/scan 新增薪資區間(下限/上限)篩選,並延長各來源的抓取逾時。 結果表在文字與遠端篩選旁新增兩個數字輸入(薪資 下限 / 上限)。每列的自由文字薪資(от 100 000 до 200 000 ₽、120000-150000 USD、$120K–$150K 等)會被解析為數字區間,並依區間重疊進行比對;未標註薪資的列會保留,因此篩選只是縮小清單而非清空(比較不分幣別——不做匯率換算)。同時將各來源掃描的抓取逾時從 15s → 30s(可用 SCAN_FETCH_TIMEOUT_MS 覆寫):Ashby 的 includeCompensation 負載在 ×8 並發下經常超過 15s,導致每次掃描約有 30 個 Ashby 看板逾時。新增 window.Skills.parseSalaryRange/salaryInRange + i18n ×9;新增 13 項測試;套件 1060/1060。


[1.66.0] — 2026-05-28

feat(scan):RU 來源現在遍歷全部結果頁,而非僅第一頁。 hh.ru、Habr Career 與 Trudvsem 先前每次查詢只取前 ~50 筆;現在會翻到最後一頁——hh.ru/Habr 用 &page=N,Trudvsem 用 offset/meta.total——跨頁去重,並在某頁沒有新結果時(或到 50 頁安全上限)停止。像「Backend разработчик」這樣的查詢現在回傳完整結果而非一頁(如 hh.ru PHP 17 → 3 頁 55+ 筆;Trudvsem 回傳全部 72 筆)。逐頁請求保留既有的逾時 + AbortSignal。新增 4 項測試;套件 1045/1045。


[1.65.0] — 2026-05-28

feat(scan):hh.ru 改為從其公開網站抓取,而非 JSON API——任何 IP 皆可用,無需代理。 api.hh.ru 開始無論 IP 或 User-Agent 都對所有程式化用戶端回傳 403 forbidden(邊緣反爬封鎖)。而網站(hh.ru/search/vacancy)會向任何類瀏覽器用戶端回傳完整結果,因此配接器現在解析該 HTML(與 Habr Career 相同)。移除 1.64.0 的 HH_PROXY 變數與 undici 相依——無需代理、金鑰或 User-Agent。測試改寫為 HTML 解析;套件 1041/1041。


[1.64.0] — 2026-05-27

feat(scan):透過 HH_PROXY 將 hh.ru 請求經俄羅斯代理轉發。 hh.ru 以 IP(而非 User-Agent)封鎖其 API,因此單靠 HH_USER_AGENT 無法解除來自非俄羅斯出口節點的 403。將 HH_PROXY 設為俄羅斯 HTTP/HTTPS 代理 URL(如 http://user:pass@ru-host:port),則僅 hh.ru 請求經該代理轉發,其餘來源維持直連。基於 undici 的 ProxyAgent(新增執行階段相依);未設定 HH_PROXY 時完全不附加 dispatcher。新增 3 項測試;套件 1041/1041。


[1.63.2] — 2026-05-27

feat(scan):#/scan 主控台即時顯示 % 進度 + 依來源的詳細日誌。 進度條現為確定式 —— 掃描器發出進度事件(EN:依公司;RU:依查詢)經 SSE 轉發,進度條帶 “Scanning… NN%” 標籤填充(動畫條紋僅持續到首個事件)。每個來源的首次失敗(逾時 / 403 / 網路)會在主控台詳細輸出,之後的重複予以抑制。新增 1 項測試;套件 1040/1040。


[1.63.1] — 2026-05-27

style(scan):讓 #/scan 進度條更醒目。 為執行中指示器加上可見的 “Scanning…” 文字,並將進度條加高到 8px(原為細 4px),掃描時清晰可見。行為無變化。


[1.63.0] — 2026-05-27

feat(scan):依請求逾時 + #/scan 進度條。 來源請求沒有截止時間,因此卡住的上游(例如來自被封 IP 的 api.hh.ru)可能讓整個掃描掛起。新增 server/lib/fetch-timeout.mjs 包裝掃描器的 fetchImpl(makeTimeoutFetch,預設 15 秒,可用 SCAN_FETCH_TIMEOUT_MS 覆寫),為每個請求設定硬性截止;逾時來源記為非致命錯誤,掃描繼續。#/scan 在掃描期間顯示進度條(全部 9 個語系的 scan.progress)。新增 7 項測試;套件 1039/1039。


[1.62.3] — 2026-05-27

docs:釐清安裝方式(career-ops-ui 執行於 career-ops/web-ui/ 內)+ init 疑難排解,涵蓋全部 9 個語系。 將安裝小節重寫為 Option 1(一條 curl)/ Option 2(在既有 career-ops 專案內以 web-ui 複製 UI)+ CLI 指令 + 供應商設定 + Troubleshooting init 區塊。巢狀結構說明亦加入 /help §1 Setup;README 重點處彙總整個 v1.62.* 系列。僅文件,無程式碼改動。


[1.62.2] — 2026-05-27

fix(help):#/help 篩選現已支援全文檢索(可找到像 RSS 這樣的 H3 子小節)。 說明頁的搜尋/目錄篩選此前僅比對 H2 小節標題,因此 v1.62.x 的 RSS 文件(§5 Portals & sources 下的 H3)無法被找到。現在每個小節的內文也會被索引到篩選中,因此搜尋如「RSS」即可定位到 §5。純前端改動,無 API 變更。


[1.62.1] — 2026-05-27

feat(scan):來源篩選器加入 RSS + 修正 RSS 地點。 #/scan 的來源篩選下拉選單現在會列出 RSS(已加入 server/lib/sources/registry.mjs 與 SPA 後備清單),因此 RSS 徵才看板(LaraJobs、WeWorkRemotely 等)的結果可像任何 ATS 來源一樣篩選。RSS 轉接器不再將來源的 <category> 標籤對應到 location —— 這些非地點標籤會讓 location_filter 誤刪遠端職缺;現在 location 留空,來源即可通過地點篩選。掃描按鈕的提示/標籤與來源清單 i18n 文字已於全部 9 個語系中更新(Workable / SmartRecruiters / Workday / RSS)。已更新 i18n 快照與來源端點測試(EN 6 → 7)。


[1.62.0] — 2026-05-27

feat(scan):用於非 ATS 徵才看板的通用 RSS 轉接器。 新增 rss 轉接器(server/lib/portals/adapters/rss.mjs + server/lib/sources/rss.mjs),讓掃描器能從任意 RSS 來源擷取職缺 —— LaraJobs、WeWorkRemotely、RemoteOK、golangprojects 以及 Greenhouse/Ashby/Lever 以外的其他看板。無新增相依套件:以正規表示式解析來源,支援 CDATA 與 HTML 實體(標題/公司名去除標籤,星位碼點安全解碼)。透過 portals.yml 的 provider: rss / rss: / feed_url: 依公司啟用,不會攔截已比對到 ATS 的公司。ALL_ADAPTERS 由 6 增至 7。新增 29 項測試;已於全部 9 個 README 語系中記載。


[1.61.1] — 2026-05-22

fix(i18n):在全部 9 種語言中在地化主題切換按鈕的 title 與 aria-label(MINOR-001)。 明/暗主題按鈕(#theme-toggle)在 index.html 中硬編碼了 title="Toggle theme" 和 aria-label="Toggle theme" —— 所有語言下工具提示與螢幕閱讀器文字都未翻譯。新增 top.themeToggle 鍵 + applyI18n() 中的 data-i18n-title 處理器(沿用 v1.58.15 搜尋 aria-label 修復的模式),在啟動時及每次切換語言時在地化這兩個屬性。由 tests/playwright-theme-toggle-i18n.mjs(9 語言 + 執行階段切換)與兩個靜態守衛鎖定。v1.61.0 法語簽收中唯一的 LOW 項。(MINOR-001)


[1.61.0] — 2026-05-22

feat(i18n):新增法語作為第 9 種介面語言。 新的依語言字典 public/js/lib/locales/i18n-dict.fr.js(window.__I18N_DICT_FR)與英語完全對等(668 個鍵);新的說明包 docs/help/fr.md(19 H2 / 73 H3,與 en 結構完全對等)。fr 已註冊至語言切換器與瀏覽器自動偵測(i18n.js)、組裝器(i18n-dict.js)、index.html(位於組裝器之前的 <script> 標籤)、測試快照以及所有測試語言清單中。初始翻譯表來自 PR #9(社群貢獻)。邏輯無變更:t() 與所有視圖保持不變。單元測試 1001 / 1001;Playwright 語言巡覽擴充為 9 個子測試。(FR-LOCALE)


[1.60.0] — 2026-05-22

refactor(i18n): 將 8 語言合一的大檔案拆分為按語言的檔案 (I18N-SPLIT). 翻譯字典原先位於單一 public/js/lib/i18n-dict.js;現改為 public/js/lib/locales/ 下每種語言一個檔案外加共用的 i18n-dict.aliases.js,讓譯者可以獨立編輯單一語言(i18next / OpenWA 佈局)。i18n-dict.js 現在是一個組裝器,把各語言表重新合併成完全相同的 window.__I18N_DICT,因此 t() 與所有視圖保持不變。透過 <script src> 同步載入——無建置、無 fetch。快照證明遷移無損(678 個鍵)。工具與約 25 個測試已適配拆分;新增 tests/i18n-locale-files.test.mjs 與 tests/playwright-locale-sweep.mjs(在真實 Chromium 中逐頁 × 8 語言驗證)。994 → 1000 單元 · 62 → 70 Playwright。無行為變化。(I18N-SPLIT)


[1.59.13] — 2026-05-21

fix(i18n): 用 @alias 合併真正重複的鍵 + 個人資料最終清理. 從測試夾具/QA 報告中移除維護者真實姓名(→ Jane Doe),LICENSE/package.json 改為 Fighter90 帳號。@alias 機制合併 8 個語言完全相同的 10 個鍵。nav.config/config.title 因西班牙語不同而不合併。991 → 994 測試。(I18N-CL3)


[1.59.12] — 2026-05-21

fix(i18n): i18n-dict.js 清理 — fr 語言前 (I18N-CL1, I18N-CL2, I18N-CL4). 將 training.coursePh 中的個人資料替換為通用佔位符,followup.lastPh 由固定日期改為格式提示,新增 npm run audit:i18n。重複值分組是有意為之(不同 UI 角色)—— 見字典標頭。(I18N-CL1, I18N-CL2, I18N-CL4)


[1.59.11] — 2026-05-21

fix(test): v1.59.11 — e2e-comprehensive 套件現在 23/23 通過(之前 11/23)。 Playwright 的 page.goto 對僅改變 hash 的 URL 是 no-op,這是根因。新的 goRoute(hash) 輔助函式透過 about:blank 反彈以強制真實導航。(e2e-harness-r1)


[1.59.10] — 2026-05-21

fix(api): NEW-F1-sub-r1 (v1.59.10) — 原始 .. 守衛上移到所有 /api 路由註冊之前。 v1.59.8 的位置在 app.all 之後,從未觸發。現在它在 Express 規範化之前執行。(NEW-F1-sub-r1)



career-ops-ui v1.267.1 · page 5/9 · mirror of the project changelog for cvstart.org