変更履歴

GitHub

すべての注目すべき変更をリリースごとに記録しています。同じファイルがリポジトリに収録されており、19言語すべてに翻訳されています。

[1.228.0] — 2026-08-29

追加 — スキャンソースとしての Telegram チャンネルと、/api/scan-results のページング付きクエリモード。

追加

  • Telegram チャンネルがスキャン対象になりました。 portals.yml の telegram_channels: ブロックに列挙し、各チャンネルは公開ウェブプレビュー https://t.me/s/<チャンネル> から読みます。レジストリ: 85 → 86 ソース(EN 81 + RU 5)、ALL_ADAPTERS 80 → 81。

    Telegram は RSS を publish せず、Bot API はボットが管理していないチャンネルを読めません。つまり自明な経路は両方とも塞がっています。/s/ プレビューはサーバー生成の素の HTML で、認証も JS も Cookie も不要です。16 チャンネルで検証: 15 が素の GET で 20 件ずつ返しました。

    channel: は書き方を問いません。パーサーは Telegram の再設計が最後まで動かさないであろう 3 点 —— data-post、本文コンテナ、ISO 日付 <time datetime> —— に依拠します。

  • GET /api/scan-results にページング付きクエリモードを追加。 ?q=<テキスト>&limit=50[&region=ru|en][&set=filtered|fresh][&offset=N] が { total, returned, offset, limit, set, rows } を返します。total はページング前の件数です。パラメータなしなら従来どおりスナップショット全体を返します —— #/scan のテーブルがその形に依存しているためです。

修正

  • Telegram アシスタントはデータの一部だけで答えていました。 スキルはすでに /api/scan-results を指していましたが、このルートはスナップショット全体しか返せず、実機で約 2 MB —— エージェントのコンテキストに入りません。「Продуктовый менеджер を全部探して」に対し、スナップショットに数百件ある中で 9 件と答え、「限定的なローカルインデックスで動いている」と述べました。それは本当で、原因はエンドポイントが見えても消費できないことでした。ページングモードなら同じ質問が 2 KB で済み、正直な total を返します。スキルも書き直しました: 新着の投稿を要約せよと書かれており、filtered(残った全件)ではなく fresh(直近実行分のみ)を指していたためです。

備考

  • チャンネルの投稿は散文であり、求人レコードではありません。 構造化フィールドは存在しません: 見出しは最初の実質的な行から、会社・勤務地・給与は明示ラベルから取り、本文は説明に入れます。本物の求人を広告やダイジェストと分ける役目は既存の title_filter —— 他のソース向けに調整済みの、まさにそれ —— に委ねています。これは手がかりであって一覧ではありません。
  • 会社名は決して推測しません。 ラベルが無ければ行はチャンネル(@rabotaphp)に帰属させます。誤った雇用主はトラッカーに事実として入ってしまうからです。
  • 解析結果ゼロはエラーであり、「求人なし」ではありません。 非公開・存在しないチャンネルに t.me はリダイレクトを返します。ここでゼロ件を返せば静かな一日と読め、設定のタイプミスを永久に隠します。元の一覧の jobGeeks がまさにこれ(HTTP 302)で、意図的に設定していません。
  • リモート判定は \b ではなく Unicode の単語境界を使います。\b は ASCII 専用で、キリル文字の前の空白は境界にならないためです —— v1.227.3 でタイトルフィルターが踏んだのと同じ罠で、今回はリリース前にテストが捕まえました。
  • 15 チャンネルを設定し実データで検証: 299 投稿、15/15 チャンネル。新規テスト 28 件。テスト: 2865 → 2895。
  • The README test counts jumped by hundreds, and no, this release did not add them. The localized READMEs carried unit-test totals frozen at 1856 / 1945 / 1955 / 549 / 419 / 284 / 2527 depending on the file — each stale since a different release, and several contradicting the badge at the top of the same page. They now all read 2895, verified by running the suite rather than by copying a badge. Playwright (70 / 90 / 12 → 101), e2e smoke (20 → 21), route modules (12 / 32 → 37), smoke flows (12 → 22) and the test-file count (218 → 329) were stale in the same way. The Total row also repeated the unit count, so it under-summed the three suites below it; it now reads the real sum (3040).

[1.227.5] — 2026-08-29

修正 — 地域スキャンがサーバーのメモリを食い潰し、Playwright スイートが自身の teardown で不安定に落ちていました。

修正

  • 地域スキャンが OOM でサーバーを落としていました。 ru-scanner は全クエリの生ヒットをすべてため込み、重複排除とフィルタリングを最後にまとめて行っていました。クエリ一覧は意図的に類義語だらけ(Golang、Go разработчик、Golang разработчик、Senior Go …)なので、同じ求人がクエリごとに返り、配列はユニーク件数の数倍を保持していました —— しかも求人オブジェクトの大半を占める説明文つきで、その説明文はフィルタでほぼすべて捨てられます。実測: 21 クエリの実行でヒープ 742 MB。サーバーは Node のヒープを 490 MB に制限しており(V8 がマシンの 956 MB の RAM から算出)、スキャンは FATAL ERROR: Reached heap limit でサービスを落としました —— 1 日に 4 回。現在は重複排除とフィルタリングをクエリごとに行い、同じ実行が 177 MB に収まりました(76% 減)。報告される件数は不変です: ユニーク合計は URL 文字列の Set が保持します。
  • net::ERR_SOCKET_NOT_CONNECTED が CI をランダムに落としていました。 3 つの Playwright スイートは、コンソールエラーが無いことを検証する前に window.stop() で進行中のリクエストを止めます。Chromium はこの 1 つの意図的な操作を、ソケットの状態に応じて 3 通りの名前で報告します: 取り消し時は ERR_ABORTED、飛行中は ERR_EMPTY_RESPONSE、ソケットが既に消えていれば ERR_SOCKET_NOT_CONNECTED。共有フィルターは最初の 2 つしか知りませんでした。ロケール走査の tr で表面化しましたが、同じく window.stop() を呼ぶ playwright-forms と playwright-smoke も、不運な 1 回で同じ結果になるところでした。

備考

  • なぜ今になって落ち始めたか。 プロダクトマネージャー系の検索を足した際にクエリが 14 個から 21 個になりました。旧実装のメモリは総ヒット数に比例したため、クエリ +50% でマシンの上限を超えました。新しいクエリに問題はありません —— 長らく設定変更ひとつで破綻し得た確保パターンを露呈させただけです。
  • 重複排除の変更は挙動を保ちます。主張ではなくテストで担保しています。 tests/ru-scanner-dedup-order.test.mjs は厄介な方向 —— 後から来た重複がフィルタに落ちる場合、先に通っていた方を追い出さねばならない —— を固定し、旧実装との等価性を 200 回のランダム試行で検証します。
  • コンソールフィルターは狭いままです。 無害なのは取り消し系のみ。接続拒否、DNS 失敗、リセット、あらゆる 5xx、未捕捉の JS 例外は引き続き検証を落とします。
  • 2 つの仮説は検証のうえ破棄し、リリースには含めていません: Caddy のタイムアウト(設定はクリーンで、SSE 用の flush_interval -1 も正しい)と Node 既定の 5 分 requestTimeout(縮小再現により、長いストリーミング応答を切断しないと判明)。実際の証拠はジャーナルの Reached heap limit でした。テスト: 2860 → 2865。

[1.227.4] — 2026-08-29

修正 — word: / stem: は content_filter では依然として無視されていました。v1.227.3 が直したのはタイトルフィルターだけでした。

修正

  • content_filter がプレフィックスを尊重していませんでした。 v1.227.3 は title_filter に親の word: / stem: プレフィックスを教えましたが、content_filter は独自の素の lower.includes(k) のままで、プレフィックス付きエントリはそこでも文字列そのもの "word:java" として照合されていました —— 同じ静かな no-op が、フィルター一つ隣に残っていたわけです。content_filter は求人の説明文を読み、その既定は常に単純な部分一致でした。だからこそ素の否定 java は「JavaScript」に触れているだけの求人まで除外します。プレフィックスは、その既定から特定の 1 エントリだけを外す手段です。親の compileContentKeyword を移植しました。プレフィックスの仕組みは共有しつつ、短いキーワードの自動アンカーは意図的に行いません —— タイトルフィルターが 2〜3 文字の略語を固定するのは「Coordinator」の中の「COO」が常に誤りだからですが、説明文の段落中の短い並びは通常は意図されたもの(aws、gcp、sql、go)だからです。

備考

  • v1.227.3 の PR に対する AI レビューで発見されました。 コードが自身のコメントの主張を満たしていない —— コメントは「title_filter / content_filter」と書きながら、配線されていたのはタイトル側だけ —— という指摘です。現在のコメントは明示的に分けています: プレフィックスは両方のフィルターで有効、略語の自動アンカーはタイトルのみ。
  • 同じレビューから検証済みで、変更なし: 2〜3 文字の略語ルールを \b から Unicode 境界へ移した件は ASCII では挙動が同一で、必要な箇所でのみ厳格になります —— COO_lead と coo1 は引き続き保持(アンダースコアと数字はどちらでも単語文字)、Coordinator も保持、「Директор COO」と「VP «Продукт»」は正しく除外。14 の境界ケースを確認しました。
  • プレフィックスの無い content_filter エントリは従来の一致をバイト単位で維持し、空・欠落した説明文は引き続き通過し、中身のない word: / stem: は全部ではなく何にも一致しません。tests/content-filter.test.mjs に 6 ケース追加。テスト: 2852 → 2858。

[1.227.3] — 2026-08-29

修正 — タイトルフィルターの word: / stem: プレフィックスが黙って無視され、その行が実質無効になっていました。

修正

  • web-ui は親プロジェクトの word: / stem: プレフィックスを実装していませんでした。 title_filter(および content_filter)は既定で大文字小文字を区別しない部分一致であり、そのため素の否定 intern は「International Product Manager」や「Internal Tools Engineer」まで除外します。この既定を反転させると設定済みの全インストールが壊れるため、親はエントリ単位で精度をオプトインにしました: word:intern は単語全体のみに一致し、stem:agent は単語の先頭に一致して続きは自由(「Agentforce」と「Reagents」を区別)。web-ui にはどちらも無く、エントリを文字列そのもの "word:intern" として照合していました —— そんな文字列を含む求人タイトルは存在しません。結果としてその行は静かな no-op となり、同じ portals.yml が CLI では正しく効き、ここでは全く効かず、除外したはずのインターン求人がすべて #/scan の表に届いていました。親の title-keywords.mjs から移植し、\b(ASCII 専用で、アクセント付きやキリル文字のタイトルでは語中に一致していました)ではなく Unicode 対応の語境界(\p{L}\p{M}\p{N}_)も併せて取り込みました。

備考

  • 実際の portals.yml の確認中に発見。 そこでは素の intern が「International Product Manager」を落とさないよう、まさにこのために word:intern を導入したばかりでした。CLI ではプレフィックスが効き、web-ui は黙ってインターン求人を残していました。現在は挙動が一致します。
  • 既定は変わりません。 プレフィックスの無いキーワードは従来どおりの一致方法を保ちます: フレーズや非英字を含むもの(.NET、SAP 、L&D)は部分一致、2〜3 文字の略語は語境界固定。中身のない word: / stem: はタイポとみなし何にも一致しません —— 否定として空パターンは全タイトルに一致し、コロン一つでスキャン全体を無効にしてしまうためです。
  • 2〜3 文字の略語ルールも同じ Unicode 境界に統一しました。従来は \b を使っており、非 ASCII のタイトルで coo と word:coo が食い違っていました —— 一つの規則に二つの書き方があった状態です。
  • tests/title-filter.test.mjs に 6 ケース追加。テスト: 2846 → 2852。

[1.227.2] — 2026-08-29

修正 — 幅の狭い端末で #/config が横にはみ出していました。

修正

  • MOBILE-1: 幅 352 px 以下のビューポートで #/config が横方向にあふれていました。 select 系のフィールドはすべてインラインの min-width: 300px を持っていました。インラインスタイルはスタイルシートに優先するため、コントロールはコンテナに合わせて縮むことができず、320 px のビューポートでは select の右端が 353 px に達し、ページに横スクロールが生じてコントロールが右端の外へ押し出されていました。対象はプロバイダー/モデルの select 18 個すべて(cfg-llm-provider と全 cfg-*-model)。現在は min-width: min(300px, 100%) と max-width: 100% により、余裕がある場合にのみ 300 px の快適幅が適用されます。しきい値以下の端末: iPhone SE(第 1 世代、320 px)、旧 Android、Galaxy Fold の外側画面。

備考

  • これまでのモバイル確認がすべて見逃した理由。 360 px と 375 px にはあふれを隠すだけの余裕がちょうどあり、Playwright のスイートは幅 1280 px のウィンドウで動きます。CI で 375 px より狭いビューポートを測定したものは一つもありませんでした。新しい tests/playwright-narrow-viewport.mjs はフォームを持つ各ルートを 320 px で走査し、横方向のあふれがあれば失敗し、最も右に張り出した要素をメッセージに示します。2 つ目のケースは #/config のどの select もビューポートを超えないことを固定します。まずバグを再現することを確認済みです(scrollWidth 353 > clientWidth 320、右端 353 の select が 18 個)。Playwright: 99 → 101。
  • 既知かつ意図的にまだゲート対象外: 280 px(Galaxy Fold の外側画面)は約 5 px のあふれが残りますが、原因は別です — 設定カードの <details> ブロック内の長いコンテンツと、280 px のビューポートに対する 256 px のサイドバーであり、本リリースが修正したインライン min-width ではありません。主要な端末が申告しない幅に合わせた再レイアウトは別作業で、スイートの WIDTHS リストは対応済みです。
  • v1.227.1 の QA プロンプトも修正しました。フォローアップのルートを #/modes/followup と記載していましたが、mode ページはスラッグをそのまま登録するため(Router.register(cfg.slug))、正しくは #/followup で、#/modes/followup は正しく 404 になります。ドキュメントのみ。
  • ユニットスイートは 2846 のまま(今回の追加はブラウザーレベルの網羅です)。

[1.227.1] — 2026-08-29

修正 — ヘルプのソース内訳が自身と食い違い、GitHub 用バナーがアプリで生のマークアップとして表示されていました。

修正

  • §17 の合計と内訳が合っていませんでした。 どのヘルプバンドルも「server/lib/sources/ レジストリは 85 個のアダプタを同梱 — 英語圏 78 個 + ロシア系 5 個」と記載していました。78 + 5 = 83 で 85 ではなく、ja/ko はさらにずれて 77(= 82)でした。新しいソースを追加するたび合計だけを更新し、内訳は据え置いたため、両者は複数リリースにわたって乖離していました。内訳は全 17 ロケールで EN 80 + RU 5 になりました。これは体裁の問題にとどまりません。docs/help/<lang>.md は「Ask the docs」が根拠にする唯一のコーパスであり、対応ソース数を尋ねたユーザーは一つの文から矛盾する二つの数字を受け取っていました。
  • 同じ文が古いバージョンアンカーを固定していました。 「v1.213.0 時点でレジストリは …」が 16 ロケールに残る一方、カウンタは二度動いています(v1.219.0 で 83、v1.226.0 で 85)。このアンカーは v1.210.1 で一度手作業で直されており、再び流れました。バージョンを含まない表現に置き換えて削除しました — カウンタ自体は生きたレジストリと突き合わせて検証され、古くなりようがありません。
  • プロバイダーバナーが #/help の先頭にエスケープ済みマークアップとして表示されていました。 v1.225.0/v1.225.1 は「UI.md() に画像サポートがないためアプリ側では除去される」と記録していました。これは二つの別物を混同しています。UI.md() はエスケープ優先であり、markdown 変換の前にソースの全バイトをエスケープします。これは XSS 境界として正しい設計ですが、除去とは逆です。誰も除去を試みなかったため誰も除去せず、17 ロケールすべてが #/help を 268 文字の生の <p align="center"><img src="https://… で開いていました。新しい共有入口(server/lib/help-markdown.mjs::stripGithubOnlyBlocks)が読み込み時に単独の HTML 画像ブロックを取り除きます — GET /api/help/:lang と docs-assistant のコーパスの両方で。ファイル側にはバナーが残るため、GitHub のショーケースはこれまで通り表示されます。
  • ケイデンスボードの「#」列は v1.117.0 以来空でした。 entry.appNum を読んでいましたが、followup-cadence.mjs が返すのは num で、appNum はペイロードに一度も存在しませんでした。現在は両方を読みます。v1.227.0 の「Next up」行も同じ誤りを引き継いでおり、あわせて修正しました。

備考

  • 4 件とも、ゲートが無かったために見過ごされてきました。 ヘルプのゲート(canonical-docs-coverage, help-ui, help-ru-config-section)は見出しを数えるもので — 32 H2 / 121 H3 — 段落内の数値を読んだテストも、ヘルプ入口が実際に何を返すかを見たテストも存在しませんでした。新しい 2 つのスイートがこれを塞ぎます: tests/help-source-counts.test.mjs(記載された合計が SOURCES.length と一致し、内訳が生の EN/RU 分割と一致して合計になり、段落がバージョンを固定しないこと)と tests/help-banner-strip.test.mjs(バナーは GitHub 用にディスク上へ残り、strip 後は決して残らず、各バンドルの最初の描画行が見出しであり、strip が狭いままで、両方の利用側がそこを通ること)。いずれもコミット前に、まさにこれらのバグに対して赤になることを確認済みです。テストスイート: 2837 → 2846。
  • レジストリ・スキャナー・ルート契約に変更はありません。ソースは 85(EN 80 + RU 5)、ALL_ADAPTERS は 80 のままです。

[1.227.0] — 2026-08-28

追加 — SEEK 香港(JobsDB)、フォローアップの要対応のみ絞り込み、そして非公開の雇用主が仲介エージェンシーを表示。

追加

  • 既存の Jobstreet/SEEK ソース経由の JobsDB 香港。 香港は JobsDB ブランドで運営されていますが、同じ v5 エンドポイントの背後にある同一の SEEK プラットフォーム上にあるため、別ソースは不要です —— ホスト許可リストへの hk.jobsdb.com と siteKey: HK-Main だけで足ります。レジストリは据え置きで 85 ソース(EN 80 + RU 5)、ALL_ADAPTERS 80 —— 既存アダプターに加わった新しい市場であり、新規アダプターではありません。
  • ケイデンスボードの要対応のみ絞り込み(#/modes/followup)。新しいチェックボックスで、いま対応が必要なものだけに絞れます。要対応かどうかは親プロジェクトの followup-cadence.mjs が算出済みの urgency(urgent / overdue)から読み取り、トラッカーの status は決して使いません —— そちらは applied/responded/interview であり、何にも一致しないためです。要対応が無いときは、空表示のかわりに直近の予定フォローアップを提示します。ロジックは親の followup-view.mjs を写した純粋モジュール public/js/lib/followup-view.js にあります。
  • 非公開の雇用主は、仲介したエージェンシーとして表示されます。 雇用主が伏せられた求人はトラッカーに ? として記録され、リクルーターは Via 列に入ります。#/tracker は素の ? を出すだけだったため、複数の非公開行を区別できず、ロゴ解決も手がかりを持てませんでした。今後そうした行は 「非公開 · <エージェンシー> 経由」 と表示され、ロゴはエージェンシー名から解決され、検索欄でもその名前で見つかります。表示のみの変更です —— 正本の company フィールドをリクルーターで上書きすることはありません。親の company-presentation.mjs を写した新しい純粋モジュール public/js/lib/company-presentation.js。

修正

  • Jobstreet/SEEK が廃止済みエンドポイントを呼んでいました。 ソースは SEEK が終了した chalice-search v4(/api/chalice-search/v4/search)を指したままでした。親は /api/jobsearch/v5/search へ移行済みでしたが、web-ui は追随していませんでした。今後すべての Jobstreet/SEEK エントリが v5 を照会します。v5 のアイテム形状をそのまま読み(id から URL を生成、locations[0].label、advertiser.description、salaryLabel)、v4 専用の射影パラメータ solrFields は削除、portals.yml が死んだ v4 パスを指したままのエントリも、市場のホスト名は保持しつつパスだけ v5 に組み直されます —— 利用者の編集は不要です。

備考

  • career-ops 1.30.0 パリティ(親 HEAD 8d64f65 → 6cc46a4; 親の VERSION はまだ 1.30.0 —— release-please が main より遅れています)。未移植とその理由: iCIMS の JSON-LD 位置補完 —— web-ui の iCIMS ソースには enrichDate() 詳細ページフックが存在せず(一覧ページのみ)、直すべき経路が無い; 非致命的な CLI stderr(#1974) —— web-ui のランナーは終了コードのみで失敗を判定し、そのヒューリスティックを持たない; Turbopack のパストレース —— web-ui にバンドラーは無い; cv-sync-check の修正 —— 読み取り専用のフェイルソフト中継; scan.mjs の Playwright 逐次化、Block H 回答、updater/doctor/update-system のガード、再帰的な構文チェック、Go 製ダッシュボード、jd-skill-gap/verify-cv-facts の自己テスト追加 —— web-ui が呼ばない CLI 専用の面、または挙動を変えない自己テスト。テストスイート: 2818 → 2837。

[1.226.0] — 2026-08-27

追加 — ベトナムの求人ソース2つ: ITviec と CareerViet。

追加

  • ITviec + CareerViet(ベトナム)。 ホスト固定のベトナム系ボード2つが provider: itviec / provider: careerviet エントリでスキャナーに加わります: ITviec(itviec.com、技術系)と CareerViet(careerviet.vn、広範)。いずれもトークン不要の HTML スクレイパーで、SSRF ホスト固定・HTTPS 限定・会社ごとのフェイルソフト・ページ上限を備えます。レジストリは 85 ソース(80 EN + 5 RU)、ALL_ADAPTERS 80 —— 両方が #/scan のソースフィルターに表示されます。

備考

  • career-ops 1.30.0 パリティ(parentVersion 1.29.0 → 1.30.0)。未移植(CLI/コミュニティ専用または既対応): Hired Wall、/calibrate、clean-markers、テンプレートパック、doctor、pdf/LaTeX、web-ui が呼ばない eval/tracker/scan CLI 群; _html-to-text 修正と detect-reposts roleFuzzyMatch は既存; title-filter stem: プレフィックスは保留。テストスイート: 2818。

[1.225.1] — 2026-08-27

修正 — プロバイダーロゴのバナーが README とヘルプで表示されるようになりました。

修正

  • v1.225.0 のバナーが GitHub で表示されませんでした: 単体の images/providers.svg の font-family に入れ子の二重引用符(GitHub が拒否)があり、<img> がリポジトリ相対の src(GitHub は raw HTML <img> の相対パスを解決しません)を使い、<p> ブロックに末尾の空行が無く次の行と結合していました。現在は絶対 raw URL でレンダリング済みの images/providers.png を指し、空行で区切られています。SVG も正しい XML に修正しました。

備考

  • ドキュメントのみ; コード/テストの変更なし。cvstart.org のショーケースとアプリのタイルは既に正常でした(インライン SVG、このファイルではない)。 2784

[1.225.0] — 2026-08-27

追加 — README とヘルプガイドにプロバイダーロゴのバナー。

追加

  • プロバイダーロゴのバナー。 単一の自己完結型 images/providers.svg —— 18 の LLM プロバイダーを、アイコンを公開する11は実際のブランドロゴ(simple-icons、CC0)、残る7はブランドカラーのモノグラムで —— が README(×17)とアプリ内ヘルプガイドの先頭に表示されます。(アプリは実際のロゴタイルを自前で描画します。バナーは GitHub で表示され、アプリの XSS 安全なレンダラーが取り除きます。)

備考

  • ドキュメントのみ —— コード/テストの変更なし; SVG はインライン(リモートアセットなし)。スキャンソースは変更なし: 83。テストスイート: 2784。

[1.224.0] — 2026-08-26

変更 — LLM プロバイダーのタイルが実際のブランドロゴを表示するようになりました。

変更

  • 実際のプロバイダーロゴ。 プロバイダータイル —— 設定の API キー欄、使用状況の行、ダッシュボードのチップ、設定の「アクティブ」サマリー、⚡ 評価結果、オンボーディングバナー —— が、オープンソースのアイコンを公開している11のプロバイダー(Anthropic · Gemini · OpenAI · Qwen · OpenRouter · GitHub · DeepSeek · Kimi · MiniMax · Mistral · Ollama; simple-icons の単一パス SVG、CC0)について実際のブランドロゴを表示します。公開アイコンのない7つ(Hermes · GLM/Z.ai · Grok · Together · Fireworks · BytePlus Ark · Volcengine Ark)はブランドカラーのモノグラムのままです。依然として構造的に CSP 安全: ロゴパスはインラインの静的定数 —— リモートアセットなし、innerHTML なし。

備考

  • ルートや動作の変更なし; 同じ ProviderLogo.el(slug) API。provider-logo.js は大きくなりました(インラインのロゴパス)。スキャンソースは変更なし: 83。テストスイート: 2784。

[1.223.0] — 2026-08-26

修正 — 成功した ⚡ ライブ評価がエラーとして着色されていた問題。さらに OpenWorker コワーカーを GitHub URL または .zip から直接インストール。

修正

  • ⚡ 評価結果バッジの色。 成功したライブ評価がもう失敗として着色されません。インプロセスのプロバイダー(OpenRouter、DeepSeek、…)はサブプロセスの終了 code を返さないため、厳密な code === 0 が偽になり、すべての成功が(“exit 0” と表示しつつ)赤でした。色は結果に従うようになりました — 非ゼロで終了したサブプロセスのみ赤、コードのないライブ結果は badge-ok、“· exit N” の接尾辞は実際の終了コードがある場合のみ表示されます。

変更

  • OpenWorker コワーカーを GitHub URL / .zip からインストール。 コワーカーのドキュメントに、ワンコマンドのインストーラー(curl … | bash、冪等 — 既存の career-ops / web-ui を再利用)と OpenWorker の3つのインストール経路(GitHub URL · .zip · 単一ファイルのインポート)が docs/integrations/openworker.md、アプリ内ヘルプ §32(×17)、README に記載されました。

備考

  • 長年のカバレッジの穴を塞ぎました: Recruitee ソースに v1.214.2 の引用符付き山括弧の修正(タグ属性内の > が説明に漏れてはならない)のエンドツーエンドテストを追加。スキャンソースは変更なし: 83。テストスイート: 2783。

[1.222.0] — 2026-08-26

変更 — 拡張プロバイダー(DeepSeek … Volcengine Ark)のフィールドヒントが 17 言語すべてにローカライズされました。

変更

  • プロバイダーのフィールドヒントをローカライズ。 v1.216.0–v1.217.0 で追加された 11 の OpenAI 互換プロバイダー(DeepSeek · GLM/Z.ai · Kimi · MiniMax · Mistral · Grok · Together · Fireworks · Ollama · BytePlus Ark · Volcengine Ark)の各 config.<slug>Hint —— 設定 → API キーの API キー・モデル・ベース URL のヒント —— が、英語へのフォールバックではなく 17 ロケールすべてに翻訳されました。登録 URL、モデル id、⚡ ライブ評価マーカーはそのまま保持されます。

備考

  • 動作の変更なし —— field-specs.js の英語 hintFallback はキー欠落時に依然として保護し、新しい契約テストがすべてのフィールド記述子 hintKey が 17 ロケールで解決されることを検証します。スキャンソースは変更なし: 83。テストスイート: 2779。

[1.221.0] — 2026-08-26

セキュリティ — スキャナー fetch 経路の DNS リバインディング多層防御。

セキュリティ

  • スキャナーの HTTP コア(server/lib/http-json.mjs の fetchJson/fetchText)は、実ネットワーク経路で各ソースのホストを解決し、プライベート/ループバック/リンクローカル/CGNAT/クラウドメタデータのアドレスに解決される場合は接続を拒否するようになりました。スキャナーのホストは既に公開ドメインに固定されているため多層防御であり、ユーザー URL 経路には既により強い接続固定(safe-fetch.mjs)があります。ガードは実際の fetch トランスポートでのみ動作し、注入されたテスト用 fetchImpl は解決されません。

備考

  • 正常なスキャンでは挙動変化なし。スキャンソースは 83 で変更なし。テスト: 2775。

[1.220.0] — 2026-08-26

追加 — 1 つのエントリーで複数の Get on Board カテゴリーをスキャン。

追加

  • getonbrd エントリーで programming フィードだけでなく categories: [programming, operations-management, machine-learning-ai](または単一の category:)を指定できます。求人はカテゴリー間で URL により重複排除され、上限は 12 件。既存エントリーはそのまま(既定は programming)。

備考

  • サーバーのみ。SSRF ホストピン(www.getonbrd.com)と redirect:'error' は不変で、不正なカテゴリースラッグはリクエスト前に拒否されます。スキャンソースは 83 で変更なし。テスト: 2771。

[1.219.0] — 2026-08-26

追加 — Torre がスキャナーに加わり、すべてのプロバイダーラベルが正しくなりました。

追加

  • Torre(provider: torre)— torre.ai の汎ラテンアメリカ人材マーケットプレイス。Greenhouse/Lever/Ashby に載らないリモート求人を含む認証不要の公開検索で、エントリーごとに 1 回の上限付きリクエスト。レジストリは 83 ソース(英語 78 + ロシア語 5)に。さらにオンボーディングバナーにアクティブなプロバイダーのモノグラム。

修正

  • a16z Speedrun のスキャンが、ローテーションするボードで早期に停止していました(スイープ中の短いページを最後のページとみなし、約 300 件中 149 件で打ち切り)。今はフィードの total_pages を信頼します。またオンボーディングバナーは 4 項目のマップからプロバイダーを解決し、残り 14 は生のスラッグを表示していましたが、18 のラベル+モノグラムを使うようになりました。設定のプロバイダー注記は 7→18 に。

備考

  • Get on Board のエントリーごとの複数カテゴリー指定はまだ未対応です(ソース側のリファクタが必要)。テスト: 2768。

[1.218.0] — 2026-08-26

追加 — プロバイダーが表示されるあらゆる場所にバッジ(と正しい名称)。

追加

  • ダッシュボードのチップ、設定の「アクティブ」概要、⚡ 評価結果ヘッダーのプロバイダーモノグラム。

修正

  • 古いラベル: 3 つの画面が 5 項目のマップから名称を解決していた(評価結果は Anthropic 以外をすべて「Gemini」と誤表示)。共有の ProviderStatus.label(18)を使うように。キー数の「/ 7」表示を 18 に修正。LLM_PROVIDER ヒントのスラッグ一覧に 17 言語すべてで ark / arkcn を追加。

備考

  • クライアントのみ、CSP セーフ。サーバー変更なし。スキャンソース: 82。テスト: 2758。

[1.217.1] — 2026-08-26

テスト強化 — 全プロバイダーのエンドポイントカバレッジ。

追加

  • Kimi・MiniMax・Mistral・Fireworks のエンドポイント、既定モデル、Bearer 認証を検証するパラメータ化 run<Provider> テスト。

[1.217.0] — 2026-08-26

追加 — Ark が LLM の一覧に加わりました(18 プロバイダー)。 ByteDance の Doubao モデルである BytePlus Ark と Volcengine Ark が ⚡ ライブプロバイダーになりました。同じ OpenAI 互換コアと地域別ベース URL を使います。

追加

  • BytePlus Ark(ARK_API_KEY、国際)と Volcengine Ark(ARK_CN_API_KEY、中国)— runOpenAICompatible() 経由の OpenAI 互換 Chat Completions。ARK_MODEL / ARK_CN_MODEL(Doubao のモデル名または ep-… エンドポイント id)を設定し、ARK_BASE_URL / ARK_CN_BASE_URL で地域を切り替えます。どちらも auto 順(最後)に加わり、設定と使用状況にモノグラムが表示されます。Web UI は 18 プロバイダーに対応しました。

備考

  • 他と同じ信頼された設定 + http(s) スキームチェックの経路(求人 URL 用 SSRF バリデーターは通りません)。スキャンソースは 82 で変更なし。テスト: 2755。

[1.216.0] — 2026-08-26

追加 — LLM プロバイダーを 9 つ追加、それぞれにブランドタイル。 ⚡ ライブ評価を DeepSeek、GLM (Z.ai)、Kimi (Moonshot)、MiniMax、Mistral、Grok (xAI)、Together、Fireworks、または完全ローカルの Ollama で実行できるようになりました。キー 1 つで使え、設定の各フィールド横にモノグラムが表示されます。

追加

  • OpenAI 互換プロバイダー 9 種。 DeepSeek、GLM (Z.ai)、Kimi (Moonshot)、MiniMax、Mistral、Grok (xAI)、Together AI、Fireworks AI、Ollama(完全ローカル、キー不要)。設定でキー(Ollama は OLLAMA_BASE_URL)を設定すると Hermes の後の auto 順に加わります。LLM_PROVIDER で任意の 1 つに固定できます。Together は Thinking Machines の Inkling(thinkingmachines/Inkling)もホストします。Web UI は 16 プロバイダーに対応しました。
  • プロバイダーのモノグラムタイル。 CSP セーフなブランド色のイニシャルタイルが、設定のキー欄横と使用状況ページの行に各プロバイダーを表示します。インライン SVG で、外部ロゴなし、何も端末から出ません。

備考

  • プロバイダーのベース URL は信頼された設定で、runOpenAICompatible() により http(s) スキームチェック(Ollama のループバックは許可)を通り、求人 URL 用の SSRF バリデーターは経由しません。スキャンソースは 82 で変更なし。テスト: 2752。

[1.215.0] — 2026-08-26

追加 — 求職活動のすべてを OpenWorker から実行。 新しい coworker が Andrew Ng のオープンソース AI coworker アプリからこのパイプラインを動かし、アプリ内ヘルプがそれをカバーするようになったので、Ask-the-docs アシスタントが案内できます。

追加

  • OpenWorker coworker。 コード不要の OpenWorker coworker — Fighter90/career-ops-coworker — が求職活動のすべて(スキャン・スコアリング・テーラリング・トラッキング・フォローアップ)を実行し、このダッシュボードを起動でき、すべてデスクトップで完結します。17 言語で提供される 1 ファイルのペルソナで、OpenWorker 自身のローダーでインストール可能と検証済みです。
  • ヘルプ §32「Run it from OpenWorker」(17 ロケール全部)がこれを説明するので、アプリ内の Ask the docs アシスタントとフローティングのヘルプボタンが質問に答えられます。ランディングのフッター、README、Wiki、docs/integrations/openworker.md からもリンクしています。

備考

  • ドキュメント+サイトのみ — アプリのコード変更なし。スキャンソースは 82 で変更なし。テストスイート: 2742。

[1.214.2] — 2026-08-25

修正 — 共有の HTML→テキスト パイプライン(Greenhouse / Recruitee の説明)が、属性値に > を含む場合にタグ属性を説明へ漏らさなくなりました。

修正

  • 属性内に > を含む HTML 説明が正しく除去されます。 Greenhouse・Recruitee の説明を支えるタグ除去は最初の > で止まる単純な一致を使っていたため、<a title="salary > 100k"> のようなタグが末尾の属性テキスト(100k">)を説明に残していました。いまや引用符付きの属性値(単一・二重)を尊重し、エンティティをデコードする前にマークアップを除去し(属性内のエンコードされた引用符が偽の区切りにならないように)、プレーンテキストのリテラル <> はそのまま保持します。

備考

  • テストスイート: 2742。スキャンソースは 82 で変更なし。今回、親から新規のものはありません: 残りの変更は読み取り専用でリレーされる(follow-up / weekly-digest / rejection-latency / salary-gap の修正は web-ui の変更不要)か、web-ui の対象外です(外部の X/Xquik BYO-key プラグイン、CLI/verify 修正)。任意の項目 — SmartRecruiters の詳細説明、detect-reposts のアグリゲーター スキップ、stem: / word: タイトル接頭辞、DNS リバインディング対策 — は引き続き待機中です。

[1.214.1] — 2026-08-25

修正 — Ashby の求人説明が Greenhouse・Recruitee と同じ長さで打ち切られるようになり、コンテンツフィルターが 3 ボードで同一に動作し、1 つのボードがスキャンキャッシュを肥大化させられなくなりました。

修正

  • Ashby の説明が他ボードと同じ長さ上限を守るようになりました。 v1.214.0 は Ashby の求人本文をコンテンツフィルターに渡していましたが、4000 文字で打ち切る Greenhouse・Recruitee と違い、Ashby は上限なしでそのままマッピングされていました(一部は 4 倍長い)。そのため同じ content_filter のキーワードが、テキスト内の位置だけで Ashby ではマッチし Greenhouse ではしないことがあり、1 つのボードが #/scan の読み込むスキャンキャッシュに数百 KB を追加し得ました。Ashby も同じ 4000 文字で打ち切られます(すでにプレーンテキストなので切り詰めるだけで、タグ除去はしません)。

備考

  • テストスイート: 2738。スキャンソースは 82 で変更なし。

[1.214.0] — 2026-08-25

修正 — Greenhouse・Ashby・Recruitee の求人説明がコンテンツフィルターに渡るようになり、キーワード / 国 / ビザのフィルターがこれらのボードに実際にマッチします。また「Associate <シニア職名>」(学術ランクを含む)がエントリー級と誤分類されなくなりました。

修正

  • コンテンツフィルターが Greenhouse・Ashby・Recruitee で機能します。 これらのボードは各求人の本文全体を説明として持つようになったため、説明を読む content_filter(や国 / ビザのキーワードフィルター)が、ボードを素通しにせず求人本文にマッチします。Ashby と Recruitee は一覧ペイロードに本文を無料で含め、Greenhouse はすでにそうでした。3 つとも 1 つの共有 HTML→テキスト パイプラインで整形します。
  • 「Associate Director」「Associate Professor」はエントリー級ではなくシニアです。 シニアリティ分類器(skip_tiers: が使用)は、「associate」がシニア職名を修飾する場合でもエントリー級の目印として扱っていました。いまや「Associate <シニア名詞>」—学術ランク(Associate Professor, Associate Dean)を含む—をシニアと読み、真のジュニア変種(Associate Attorney, Associate Editor)はエントリー級のまま保ち、先頭の「Intern, Associate Dean」は依然としてインターンシップに分類します。

備考

  • テストスイート: 2736。スキャンソースは 82 で変更なし。後続に予定: 任意の SmartRecruiters 説明補強(求人ごとの詳細取得)、detect-reposts の aggregator: true ボードスキップ、アンカー付きキーワードの stem: / word: タイトル接頭辞 — いずれも既定動作の変更ではなく任意の設定です。DNS リバインディング強化は専用のセキュリティリリースに引き続き予定されています。

[1.213.0] — 2026-08-22

追加 — シンガポールの国営求人バンク MyCareersFuture をスキャンソースに追加。修正 — Greenhouse の求人が本文全体を持つようになりコンテンツフィルターが機能し、リモートの Ashby 求人が都市のみの勤務地の裏に隠れなくなりました。

追加

  • MyCareersFuture(シンガポール)(mycareersfuture.gov.sg)— Workforce Singapore が運営するシンガポールの国営公共求人バンク向けの新しいトークン不要スキャンソースです。#/scan の ソース フィルターで選ぶか、任意の keywords リスト付きで provider: mycareersfuture の会社を追加します(Job Bank と同様、省略時はプロフィールのターゲット職種にフォールバック)。公開検索 API をホスト固定・キー不要で読みます。

修正

  • Greenhouse の求人をコンテンツでフィルターできるようになりました。 Greenhouse ボードを求人本文全体つきで取得し、求人の説明(description)としてプレーンテキストにデコードします — そのため説明を読む content_filter(や国・ビザのキーワードフィルター)が、Greenhouse の求人を素通しにせず実際にマッチするようになりました。
  • リモートの Ashby 求人が都市フィルターで落とされなくなりました。 Ashby は勤務形態(Remote/Hybrid/Onsite)をオフィス都市とは別に保持するため、完全リモートの求人も例えば「San Francisco」と読まれ、その都市をブロックする勤務地フィルターが応募できる求人を隠していました。リモート時は勤務地に「Remote」を付加し、古い isRemote フラグより workplaceType を優先するので、オフィス拠点のハイブリッド求人を誤ってラベル付けしません。

備考

  • スキャンソース: 82(英語 77 + ロシア語 5)。テストスイート: 2724。DNS リバインディング対策(接続前にホストの解決アドレスを検証)は、直接移植ではなく web-ui 固有の設計が必要なため、専用リリースに向けて待機中です。

[1.212.1] — 2026-08-21

修正 — cvstart.org のランディングがスキャナーの求人ソースを少なく数えていました(80 と表示し Job Bank(カナダ)が欠落)。アプリの 81 と再び一致し、両者が食い違うとサイトビルドが大きく失敗します。

修正

  • ランディングの「求人ソース」数がアプリと再び同期しました。 v1.212.0 以降、cvstart.org は 80 ボードを表示し新しい Job Bank(カナダ) チップが欠けていましたが、アプリ・スキャンのドロップダウン・ヘルプはいずれも 81 を列挙していました。ランディングはライブのスキャナーレジストリを読み込んで一覧を作りますが、あるソースが YAML 依存の取り込み方のせいでそのビルドで読み込みに失敗し、静かに落ちていました。Job Bank はいまやアプリの他の部分がスキャン時に行うのと同じく、その依存を遅延読み込みするため、常に表示されます。
  • サイトビルドは食い違ったソース数をもう出荷しません。 レジストリがディスク上に存在する数より少ないソースを列挙した場合(読み込み失敗ソースの兆候)、間違った数を静かに公開する代わりに明確なメッセージで失敗します。

備考

  • アプリの挙動は変わりません — スキャナーには常に 81 ソースすべてがあり、影響を受けたのはランディングページだけです。スキャンソース: 81(英語 76 + ロシア語 5)— 変更なし。テストスイート: 2687。

[1.212.0] — 2026-08-21

追加 — Job Bank(カナダ)、連邦の国営求人ボード。削除 — EchoJobs(フィードがボット遮断に)。修正 — Consider 系ボードが再び結果を返し、複数勤務地の Lever 求人が勤務地の半分を隠さなくなりました。

追加

  • Job Bank(カナダ)(jobbank.gc.ca)— どのアグリゲーターもうまく扱えない大量ボード、カナダ連邦の国営雇用サービス向けの新しいトークン不要スキャンソースです。#/scan の ソース フィルターで選ぶか、任意の keywords リスト付きで provider: jobbankca の会社を追加します(省略時はプロフィールのターゲット職種にフォールバック)。公開 ATOM フィードをホスト固定・キー不要で読みます。

削除

  • EchoJobs — 廃止。公開フィードがボット遮断の裏に回り何も返さなくなったため、残してもスキャン枠を浪費するだけでした。

修正

  • Consider 系ボードが再び結果を返します。 Consider は検索リクエストを受ける前に匿名ハンドシェイク(セッション Cookie + CSRF トークンを仕込む GET)を要求するようになりました。それなしではリクエストが静かに拒否され、ボードが空に見えていました。
  • 複数勤務地の Lever 求人が勤務地の半分を隠さなくなりました。 Lever は主要都市 1 つを location に、残りを allLocations に置きます。主要のみ読むと、バルセロナ AND モンテビデオで開く求人がバルセロナ限定に見えていました(勤務地フィルターで誤って除外)。両方をマージします。

備考

  • ページ間ペーシングを緩やかに(150 → 250 ms)し、単一ホストの採用サイトに配慮します。スキャンソース: 81(英語 76 + ロシア語 5)— 変更なし(Job Bank 追加・EchoJobs 削除)。テストスイート: 2685。

[1.211.0] — 2026-08-19

追加 — 台湾のテック求人ボード Yourator。修正 — タイトル・会社名のアクセント付きエンティティがどこでもデコードされ、名前にアクセントを含む会社が誤ってフラグされなくなりました。

追加

  • Yourator(yourator.co)— 台湾のテック/デジタル求人市場向けの新しいトークン不要スキャンソースです。#/scan の ソース フィルターで選ぶか、provider: yourator の会社を追加します。公開 JSON API を読み(キー不要・ブラウザ不要)、ボードの全ページを巡回し、各求人の実際の雇用主リンク(その ATS)をトラッキングパラメータを除いて出力します。

修正

  • アクセント付き名前エンティティがどこでもデコードされます。 共有 HTML デコーダーが Latin-1 の文字(&eacute; → é、&ccedil; → ç、…)を備えたため、D&eacute;veloppeur や Fran&ccedil;ais と書くヨーロッパのボードが、その文字列をタイトル・トラッカー・生成文書にそのまま残さなくなりました。(大文字は大文字のまま — &Eacute; は É であり é ではない — &constructor; のような照会は自分自身に解決されます。)
  • 名前にアクセントを含む会社が、自社ドメイン上にあるという理由で誤ってフラグされなくなりました。 「Işık」は「isik」に畳まれ isik.com.tr に一致し、「Société Générale」は societegenerale.com に一致します。旧チェックはアクセント文字を ASCII の基底へ畳まず削除していました。

備考

  • スキャンソース: 81(英語 76 + ロシア語 5)。テストスイート: 2667。

[1.210.1] — 2026-08-19

修正 — 「&」や引用符を含む Habr Career の求人タイトル・会社名が文字化けして届かなくなりました。

修正

  • Habr Career ソースが、タイトルと会社名の HTML エンティティを後段へ渡す前にデコードするようになりました。サーバーレンダリングのカードはエスケープされたまま(“Changellenge >>”、“Demand Forecasting & Inventory Optimization”、“ООО "М-ТЕХ"”)届くため、未デコードの「&」が自分の「&」タイトルフィルターを静かに外し(前リリースが他 5 ボードで閉じたのと同じ症状)、会社名が文字化けしたままトラッカーやレポートに届いていました。エンティティのデコードが対象 6 ソースすべてで完了しました。

備考

  • テストスイート: 2644。

[1.210.0] — 2026-08-19

追加 — スキャナー初のアフリカ求人ボード Senjob(セネガル)。さらに 5 ボードでタイトル照合を改善。

追加

  • Senjob(senjob.com)— セネガル向けの新しいトークン不要スキャンソースで、スキャナー初のアフリカのボードです。#/scan の ソース フィルターで選ぶか、provider: senjob の会社を追加します。公開一覧を素の HTTP で読み(キー不要・ブラウザ不要)、すべてのリクエストを senjob.com に固定し、HTML を解析するため、急に何も取れなくなった一覧を「求人ゼロの国」ではなく壊れたボード(表に出るエラー)として扱います。

修正

  • 「&」を含むタイトルが 5 つのボードで求人を落とさなくなりました — beesite・Cornerstone(csod)・Hacker News「Who is hiring」・Phenom・TKMS はタイトルが HTML エスケープされて届くため、“R&D Engineer” のようなエスケープされた「&」が自分の “r&d” キーワードを外し、求人が静かに消えていました(“sales & marketing” の除外も発火しませんでした)。タイトル — そして Phenom の勤務地 — はフィルター前にデコードされます。

備考

  • スキャンソース: 80(英語 75 + ロシア語 5)。テストスイート: 2643。

[1.209.0] — 2026-08-17

追加 — アプリ内ヘルプが応募結果の記録方法をカバーし、「ドキュメントに質問」がそこへ案内します。

追加

  • トラッカーのヘルプ(§11)に 17 言語すべてで「結果を記録する」セクションが加わり、結果 ボタンを案内します:何が起きたかを選び(不採用 / オファー / 採用 / 辞退 / 音信不通 / 面接進行)、何をするかをプレビューして記録すると — 結果を残し、提出した CV とカバーレターを保管し、行のステータスを代わりに同期します。フローティングの「ドキュメントに質問」アシスタントはこのガイドを読むため、ステータスを手で編集するよう促すだけでなく、そのボタンへ案内するようになりました。

備考

  • 各ヘルプバンドルは 31 H2 / 119 H3 になりました(従来 118)。パリティガードを合わせて更新。ドキュメントのみ — コードや動作の変更なし。スイート: 2625。

[1.208.2] — 2026-08-16

修正 — スマホで通知・テーマのボタンが検索ボックスに重ならなくなりました。

修正

  • v1.208.1 で上部バーのボタンがページ見出しに重なる問題は解消しましたが、極端に狭くはない狭い画面 — 特にボタンのラベルが長い言語 — では、バー全体がなお 1 段に詰め込まれ、🔔・🌙 ボタンが検索ボックスの上に載ることがありました。アクションボタン(通知・テーマ・診断・Scan を開く)は、スマホでは常に幅いっぱいの 2 段目に下りるようになり、検索ボックスは全体が見えて何も重なりません。

備考

  • スマホでは上部バーのアクションボタンが幅いっぱいの 2 段目へ移り、レイアウトが余った負の空きを重なりとして配っていた脆い「ほぼ満杯の段」帯を解消しました。Playwright ガードが正確な誘発条件 — ラベルの長いロケール × 565–640px の帯 — を再現し、上部バーのコントロールがピクセルを共有しないことを確認します。スイート: 2621。

[1.208.1] — 2026-08-16

修正 — スマホで上部バーのボタンがページに重ならなくなりました。

修正

  • v1.208.0 は狭い画面で上部バーのアクションボタン(診断・Scan を開く・通知・テーマ)を 2 段目に折り返しましたが、バーの高さが固定だったため、折り返した段がはみ出してページ見出しの上に重なっていました。バーは段に合わせて伸びるようになり、コンテンツはその下に流れます。

備考

  • 上部バーの固定 height を min-height にしたので、どの幅でも内容に合わせて伸びます(デスクトップは不変)。Playwright ガードが上部バーのはみ出しも確認します。スイート: 2621。

[1.208.0] — 2026-08-16

修正 — アプリがスマホ画面に収まるようになりました: 横スクロールが解消。

修正

  • 狭い画面ではアプリ全体が横にはみ出していました — トップバー、表、ヘルプ記事、設定タブが右端を越えていました。どの幅でも各ページが収まります: トップバーのボタンは 2 段目に折り返し、幅の広い表やコードブロックは自身のボックス内でスクロール、ヘルプは目次を記事の上に積み、ボタン/タブの行は折り返し、長いパスや URL はページを広げずに改行します。

備考

  • 原因は典型的な flex/grid の min-width: auto の罠と、折り返されない幅広要素でした。grid アイテムの min-width: 0、マークダウン/見出しの overflow-wrap、スクロール可能なマークダウン表、モバイルブレークポイントでのヘルプグリッドの段組みで解決しました。Playwright ガードが主要ルートで 375px で横オーバーフロー 0 を検証します。tests/playwright-smoke.mjs。スイート: 2621。

[1.207.2] — 2026-08-16

修正 — AI プランとキャリア方向づけプロファイルが生のコードダンプとして表示されなくなりました。

修正

  • 一部のモデルは回答全体を markdown … のコードフェンスで包みます。そのとき 育成プラン と 方向づけプロファイル が、見出しやリストのある文書ではなく等幅のコードブロックとして表示されていました。包んでいるフェンスを取り除くようにしました — 回答全体を包み、言語が明示的に markdown/md のときだけなので、本物の python/js/言語なしの ``` コード回答はそのまま残ります。

備考

  • 共有の LLM 整形ステップ(cleanLlmMarkdown)で一度に処理するため、すべての AI ルートが恩恵を受け、包まれた回答内のコードブロックも残ります。tests/llm-output.test.mjs(+3)。スイート: 2621。

[1.207.1] — 2026-08-16

修正 — 小さなスマホでランディングページが横にはみ出さなくなりました。

修正

  • 幅の狭いスマホでは、ヒーロー領域(見出し・導入文・インストール用ターミナル)が右端で見切れることがありました。長いインストールコマンドとレイアウトの列が画面に合わせて縮まなかったためです。どの幅でも収まるようになり、インストールコマンドはターミナルの箱の中でスクロールします。

備考

  • また、一時的なリソース 404 で失敗し得た不安定な E2E スモークチェックを強化しました。姉妹チェックと同様に無害なネットワークノイズ(favicon/接続/リソース失敗)を無視しつつ、実際のスクリプトエラーは引き続き検出します。アプリの挙動は変わりません。スイート: 2618。

[1.207.0] — 2026-08-15

追加 — トラッカーから応募の結果を直接記録できます。

追加

  • すべてのトラッカー行に 結果 アクションが付きました: 何が起きたか(不採用・オファー受領・採用・オファー辞退・返信なし・面接に進んだ)を選び、任意のメモを添え、結果のステータスをプレビューしてから記録します。記録すると提出した CV・カバーレターの成果物を保管し、トラッカーを正規の状態に同期します — 手作業の編集ではなく決定論的な 1 アクションです。

備考

  • 新しい POST /api/outcome が結果 CLI を中継します: dryRun:true は読み取り専用プレビュー(行を照合し結果ステータスを報告、何も書き込まない)、実呼び出しは記録します。書き込み安全性: 結果タイプは既知の集合にホワイトリストし、すべてのテキストフィールドはシェル呼び出し前に制御文字を拒否します(配列引数、spawn — シェルなし)。tests/outcome-route.test.mjs。スイート: 2618。

[1.206.0] — 2026-08-15

ドキュメント — アプリ内ヘルプガイドが最新の 5 機能を 17 言語すべてでカバーしました。

追加

  • アプリ内ヘルプガイドと、それを根拠に回答する「ヘルプに質問」アシスタントが、最近追加された 5 つの機能を説明するようになりました: セットアップドクター(設定 — CV とプロフィールの不足やサンプルデータの残りを点検)、ATS ボードを探す(ポータル — 企業の採用ボードを自動検出)、「まだ募集中?」チェック(トラッカー — 求人がまだ開いているか)、「過去の CV を再利用?」ヒント(CV スタジオ — 調整済みの CV が新しい求人に合うかを通知)、スキルログ(分析 — 自己評価スコアを記録)。新しいサブセクション 5 つを 17 言語に翻訳しました。

備考

  • ヘルプ構成は 31 個の H2 / 118 個の H3 に増え、全ロケールでパリティが保証されます。参照ドキュメントを更新: docs/architecture/API.md がこれら機能の 5 ルートを記載し、CLAUDE.md と docs/sdd/CONVENTIONS.md のルート/バージョン数が最新です(ルートモジュール 36 個)。スイート: 2610。

[1.205.0] — 2026-08-15

追加 — 試験・アセスメント結果を記録するスキルログ。

追加

  • 新しいスキルログ(分析 → スキルログ)で自己評価を記録できます — 会社・プラットフォーム・スキル・スコア %・任意のメモ — を data/assessments.tsv に追記し、新しい順の一覧で表示します。トークン不要・決定的で、ファイル形式は親 CLI が管理します。

備考

  • 新しい GET /api/assessments(assessment-log.mjs の既定 JSON リストをリレー、ソフト失敗 {available:false})と POST /api/assessments(明示的な書き込み: フィールドを配列引数として assessment-log.mjs add に渡す)。書き込み安全性: 制御文字を含むテキスト項目は拒否(TAB は列を、改行は行を壊す)→ 書き込み前に 400。スコア/しきい値は 0–100 に限定、長さも制限。tests/assessments-route.test.mjs。スイート: 2610。

[1.204.0] — 2026-08-15

追加 — 設定に「セットアップ・ドクター」パネル。未完成や例データの残る CV/プロフィールを指摘します。

追加

  • 設定 → セットアップ・ドクターが、トークンを使わずに cv.md と config/profile.yml を点検し、ブロッキングな問題(欠落したファイル/項目)と警告(残った例・プレースホルダーデータ、ハードコードされた数値)を一覧します — 未完成の設定がスキャンや調整を弱める前に気づけます。読み取り専用、ワンクリックで再実行。

備考

  • 新しい読み取り専用 GET /api/cv-sync-check が親プロジェクトの cv-sync-check.mjs(人間可読テキスト + 終了コードを出力、--json なし)をリレーします。ルートは安定した ERROR: / WARN: 行を軽く構造化して {ok, errors[], warnings[]} にし、成否は終了コードではなくバナーで判断します。単体インストールでは {available:false} でソフトに失敗します。tests/cv-sync-check-route.test.mjs。スイート: 2602。

[1.203.0] — 2026-08-15

追加 — CV スタジオに「過去の CV を再利用?」ヒント。

追加

  • CV スタジオで保存済みの求人を開くと、アプリが他の保存済み求人と比較し(決定的な語の重なり・トークンゼロ)、最も近いものがその調整済み CV を再利用できるほど似ているか、修正して再利用か、新規に調整すべきかを教えます — すでに狙った職種をゼロから作り直さずに済みます。

備考

  • 新しい読み取り専用 GET /api/jds/:name/reuse が親プロジェクトの jd-similarity.mjs(Jaccard の重なり + シニオリティガード、JSON {decision, score, reason})を過去の求人ごとに一度リレーします(ファンアウトは 25 上限、最良を採用)。スクリプトや過去の求人が無ければ {available:false} でソフトに失敗します。tests/jd-similarity-reuse-route.test.mjs。スイート: 2594。

[1.202.0] — 2026-08-15

追加 — #/portals から企業の ATS 求人ボードを見つけて追跡を開始。

追加

  • #/portals で企業名を入力すると、アプリが Greenhouse・Ashby・Lever の公開ボードを探索し — LLM ゼロ・ブラウザなし — 存在して現在 1 件以上掲載しているボードを表示します。1 クリックで選んだボードをスキャナーの監視対象企業に追加します。探索は読み取り専用で、portals.yml への書き込みは 追加 を押したときだけ行われます。

備考

  • 新規 server/lib/discover-ats.mjs(固定ホスト・文字種検証済みスラグを DNS ピン留めの safeGet で探索、リクエストあたり ≤12 回)+ POST /api/portals/discover(読み取り専用)と POST /api/portals/track(明示的な書き込み: withFileLock + テキストスプライス + 再パースガード + アトミック置換、既知の ATS ホストのみ、冪等)。スキャナーのアダプターレジストリを再利用してボード確認・件数計上。i18n ×17。tests/discover-ats-resolver.test.mjs + tests/discover-ats-route.test.mjs。スイート: 2588。

[1.201.0] — 2026-08-15

修正 — ローカライズ/別名の列見出しを使うトラッカーが空欄で表示されなくなりました。

修正

  • data/applications.md が英語以外や別名の見出し(スペイン語 empresa / puesto / estado / fecha / enlace、または position / stage / link)を使うと、トラッカーが誤ったキーで読み 会社 / 職種 / ステータス / 日付 / リンク列が空欄 になっていました。これらの見出しが正規のフィールド名に畳み込まれ、正しく表示されます。英語のトラッカーは従来どおり処理されます。

備考

  • parseApplications(server/lib/parsers.mjs)に新しい HEADER_ALIASES マップと正規化の畳み込みを追加。未知またはすでに正規の見出しはそのまま通過します。tests/tracker-header-aliases.test.mjs。スイート: 2563。

[1.200.0] — 2026-08-15

追加 — トラッカーで ATS 掲載求人の「まだ募集中?」をワンクリック確認。

追加

  • #/tracker で、URL が Greenhouse / Lever / Ashby / Workday / SmartRecruiters の掲載である応募に 「まだ募集中?」 ボタンが表示されます。1 クリックで ATS 自身の公開 JSON を照会し — トークン 0・ブラウザなし — 募集中 / 終了 / 不明 を表示するので、1 件ずつ開かずに消えた求人を見つけられます。保守的設計:明確な 404/410 のみ 終了 と判定し、曖昧なものは 不明 のまま(誤った 終了 を出しません)。

備考

  • 新規 server/lib/liveness-core.mjs + liveness-api.mjs と読み取り専用 GET /api/liveness?url=(書き込みなし・LLM なし)。SSRF 安全:URL を isValidJobUrl で検査し、ATS API は固定ホスト+文字種検証済みパスで DNS ピン留めの safeGet 経由でのみ取得します。tests/liveness-core.test.mjs + tests/liveness-route.test.mjs。スイート: 2557。

[1.199.0] — 2026-08-15

修正 — 幅の広い表が切れずに横スクロールするようになりました。

修正

  • Scan ページ(およびトラッカー・統計・使用量・ダッシュボードなど他のすべての表)で、ウィンドウより広い表がスクロールバーなしで切り取られ、右端の列に到達できませんでした。幅の広い表は必要に応じて横スクロールバーを表示するようになり、どの画面幅でもすべての列に到達できます。

備考

  • public/css/components.css の .table-wrap を overflow: hidden から overflow-x: auto に変更しました(既存の .reports-scroll コンテナと同じ)。角丸の枠線は保持されます。tests/table-wrap-scroll.test.mjs。スイート: 2540。

[1.198.0] — 2026-08-15

追加 — スキャンの再試行が指数バックオフとジッターを使い、レート制限の Retry-After を尊重するようになりました。

追加

  • スキャン中に求人ボードが一時的にレート制限やエラー(HTTP 429 / 5xx)を返したとき、再試行は固定の短い遅延ではなく指数バックオフ + ジッターで待つようになりました — 混雑したボードを同じ間隔で叩き続けず、同時再試行が一斉に再衝突しません。ボードが送った Retry-After は尊重されます(ただしクランプ付き — 悪意ある Retry-After: 86400 がスキャン全体を止められないように)。恒久的なエラー(404、拒否されたリダイレクト)は従来どおり即座に失敗します。

備考

  • server/lib/http-json.mjs に新しい parseRetryAfterMs() と純粋関数 computeRetryDelayMs()。fetchJson は非 ok 応答で .retryAfter を取得し、fetchJsonWithRetry は任意の maxDelayMs(既定 8000)を受け取ります。tests/http-json.test.mjs (+9)。スイート: 2536。

[1.197.0] — 2026-08-14

追加 — Getro の VC 求人ボードを careers_url だけで追跡でき、コレクション id は自動解決されます。

追加

  • 追跡中の Getro ボード(b2venture、Earlybird、Point Nine …)に、手作業で調べた数値の getro_collection はもう不要です。ボード自身の careers_url を渡せば、初回スキャン時にそのページから id が自動解決されます — SSRF 安全な GET 一回で、ページに埋め込まれたデータから数値の network.id を直接読み取ります。明示的な getro_collection は依然として優先され、取得を完全にスキップします。

備考

  • server/lib/sources/getro.mjs に新しい httpsCareersUrl()、extractCollectionId()、非同期の resolveCollectionId() を追加。ボードページは DNS ピン留め・サイズ上限付きの safeGet で取得し、解決された id は引き続き assertGetroUrl によりホストが api.getro.com に固定されます。アダプターは id がなくても https の careers_url を持つ provider: getro エントリにマッチするようになりました。tests/sources-getro.test.mjs (+8)。スイート: 2527。

[1.196.0] — 2026-08-14

修正 (セキュリティ) — Workday アダプターは api エンドポイントを部分文字列ではなくホスト名で検証します。

修正

  • portals.yml の Workday api: 値は、ホスト名が myworkdayjobs.com(または .myworkdayjobs.com サブドメイン)のときだけ受け入れられます。以前は部分文字列一致だったため、文字列を含むだけの URL — 例: https://example.com/?x=myworkdayjobs.com — も通り、エンドポイントとして使われる可能性がありました。実際の Workday エンドポイントは影響なし。(CodeQL 報告、#443。)

備考

  • 新しい isWorkdayApi() が URL を解析してホストを確認(server/lib/portals/adapters/workday.mjs)。tests/workday-adapter-endpoint.test.mjs(+1)。スイート: 2522。

[1.195.0] — 2026-08-14

パフォーマンス (スキャナー) — 大きなスキャン履歴でも再掲載検出が速いままです。

パフォーマンス

  • 大きな scan-history.tsv で重複求人検出が O(N²) に劣化しなくなりました。会社ごとのタイトルグルーピングは、すべてのペアで完全な roleFuzzyMatch を払う入れ子ループでしたが、今は転置インデックスです — 一度のパスで完全一致タイトルごとにバケット化し、判別トークン(非ベースライン)を共有する異なるバケット同士だけをファジーマッチします。出力は同一 — 同じ再掲載クラスター — 旧アルゴリズムとの差分テストを 200 以上のランダム履歴で通して証明。

備考

  • server/lib/detect-reposts.mjs の groupRowsByTitle(差分テスト用に export)。tests/detect-reposts-grouping.test.mjs(+2)。スイート: 2521。

[1.194.0] — 2026-08-14

修正 (スキャナー) — 単一セグメント URL の Workday 求人ページが正しくスキャンされます。

修正

  • Workday アダプターが、パスが単一セグメントの求人 URL を解析するようになりました — 例: https://parsons.wd5.myworkdayjobs.com/Search、.../KBR_Careers、.../Careers。以前はサイトが External にフォールバックし、誤った CXS エンドポイントを叩き、プローブが正常に見えても何も返さないことがありました。今はパスの最初の空でないセグメントをサイトとして使います(en-US などのロケール接頭辞は除外)。文書化された /en-US/External は変わりません。(#255 で報告。)

備考

  • server/lib/portals/adapters/workday.mjs の構造的パス解析。tests/workday-adapter-endpoint.test.mjs(+5)。スイート: 2519。

[1.193.0] — 2026-08-14

追加 (統計) — 一声かける価値のある面接を可視化する「面接後の沈黙」タブ。

追加

  • #/stats の 面接後の沈黙 タブ:礼儀としての期間(既定 30 日)を過ぎて静かになった面接を、進行中の面接とトラッカーを結んで表示 — 各面接がどれだけ沈黙しているか、最後の面接日、理由とともに。穏やかなリマインド/クロージャーの一覧で、提案のみ・不合格の主張ではありません。トークン不要。

備考

  • 新 GET /api/stats/rejection-latency リレー(スクリプト不在時は {available:false})。tests/stats-rejection-latency-route.test.mjs(+2)。i18n キー +10 ×17;#/stats help-hint を 7→8 タブに。スイート: 2510。

[1.192.0] — 2026-08-14

追加 (cv-studio) — 実際には無かった数字を捕まえる「CV のファクトチェック」ゲート。

追加

  • #/cv-studio の CV のファクトチェック カード:調整済みの CV やカバーレターを貼り付け、主張された数値や事実を実際の CV・プロフィール・two-pager と照合します。pass / warn / block の判定に加え、でっち上げた数値・裏付けのない事実・禁止/注意フレーズを正確に表示。LLM 不使用、何も保存しません。

備考

  • 新 POST /api/cv-studio/verify-facts リレー:テキストを使い捨ての一時ファイルに書いて verify-cv-facts.mjs を実行し、スクリプトが block で 1 終了しても JSON 判定を信頼します。tests/cv-studio-verify-facts-route.test.mjs(+4)。i18n キー +15 ×17。スイート: 2508。

[1.191.0] — 2026-08-14

追加 (統計) — まず学ぶべきスキルを順位付けする「次に学ぶこと」タブ。

追加

  • #/stats の 次に学ぶこと タブ:トラッカー全体のスキルギャップ集計 — 低適合を最も頻繁に招いた不足スキルを、重み付け(各評価レポートの 5−適合スコア)と Critical / High / Medium ティアで、さらに CV/プロフィールが既にカバーするスキルも。読み取り専用・提案のみ・トークン不要。

備考

  • 新 GET /api/stats/upskill リレー(データ不足時は { error } フィールド、スクリプト不在時は {available:false})。tests/stats-upskill-route.test.mjs(+3)。i18n キー +15 ×17。スイート: 2504。

[1.190.0] — 2026-08-14

追加 (トラッカー) — どの会社が実際に応答するかを示す「会社の履歴」パネル。

追加

  • #/tracker の 会社の履歴 カード:会社を選ぶと読み取り専用の根拠が表示されます — その会社があなたにどれだけ応答したか(無応答 / 混在 / 以前に応答あり)、同じ求人が再掲載され続けているか — トラッカー・フォローアップ・スキャン履歴を結合。トークン不要でスキャナーは呼びません。

備考

  • 新 GET /api/stats/company-history[?company=] リレー(スクリプト不在時は {available:false})。tests/stats-company-history-route.test.mjs(+3)。i18n キー +18 ×17。スイート: 2501。

[1.189.0] — 2026-08-14

修正 (スキャナー) — ローマ数字の年次レベルが非ラテン語のタイトルでも認識されます。

修正

  • skip_tiers の背後にあるティア分類器が、あらゆる文字体系で職種語の後のローマ数字レベル接尾辞(I / II / III / IV / V)を読むようになりました — 「Инженер III」「エンジニア I」「Ingénieur IV」 — ASCII 語の後だけではありません。以前は非ラテン語の後のレベル数字が無視され、求人が mid に落ち、skip_tiers: [senior] や [entry] がそれらを取りこぼしていました。

備考

  • server/lib/classify-tier.mjs の文字体系非依存の後読み。死んでいた重複 Sr. マッチャーを削除。tests/classify-tier.test.mjs(+1)。スイート: 2498。

[1.188.0] — 2026-08-14

修正 (UI) — 主要アクションボタンがページ副題に密着しなくなりました。

修正

  • 週間インタビューダイジェスト、資金調達企業、ポータル、キャリアプラン、キャリアオリエンテーション の主要アクション/コントロール行に適切な上マージンが付き、ボタンが副題にくっつかず下に余白を持つようになりました。

備考

  • リグレッションガード tests/lead-row-top-margin.test.mjs (+5)。スイート: 2497。

[1.187.0] — 2026-08-14

修正 (スキャナー) — skip_tiers 設定が再び機能: 年次でスキップ指定した求人が除外されます。

修正

  • portals.yml の skip_tiers: リスト(例: skip_tiers: [intern, entry])がスキャンで反映されるようになりました。各求人のタイトルを年次ティア(intern / entry / mid / senior)に分類し、リストに含まれれば除外します。以前はタイトル / ロケーション / コンテンツ / 信頼フィルターは実行していましたがティアフィルターが無く、skip_tiers は黙って無視されていました。レベル語のないタイトルは mid に分類され(そのため skip_tiers: [mid] は普通の求人も大半を除外)、分類器は最も左のレベル語を読みます。

備考

  • 新しい純粋モジュール server/lib/classify-tier.mjs(classifyTier + buildTierFilter)を EN・RU スキャナーのフィルターチェーンに接続。tests/classify-tier.test.mjs (+7)。スイート: 2492。

[1.186.0] — 2026-08-14

追加 (CV スタジオ) — 「スキルギャップ」パネル: 求人の必要スキルのうち CV が明記・示唆・欠落しているもの。

追加

  • CV スタジオの新しいスキルギャップパネル。保存済みの求人票を選ぶと、各必要スキルを CV に明記・CV に示唆・欠落に分類します — LLM なしの単語比較で、何も書き込みません。求人に明確な要件セクションがない場合は信頼度低の注記が出ます。

備考

  • 新しい GET /api/jds/:name/skill-gap(JD 名はパスサニタイズされ jds/ 配下の存在を確認してから引数化。スクリプトが無ければ {available:false} にソフトフォールバック)。i18n キー +13 ×17。テスト: tests/jds-skill-gap-route.test.mjs (+4、パストラバーサル拒否を含む)。スイート: 2485。

[1.185.0] — 2026-08-14

追加 (統計) — 「ファネルと速度」タブ: あなたのファネルが市場とどう比べられ、ステージ間をどれだけ速く進むか。

追加

  • 統計の新しいファネルと速度タブは、市場ベンチマークの範囲の横にあなたの返信率と面接率(小標本・選択バイアスの注意付き)、一般的な初回返信ウィンドウを過ぎた進行中応募の待機リスト、ステージごとの中央値日数(応募 → 返信 → 面接 → オファー)を表示します — 遅い行は右側打ち切りで中央値を歪めません。読み取り専用・トークン 0。あなた自身のトラッカーのみを読みます。

備考

  • 新しい GET /api/stats/funnel(スクリプトが無ければ {available:false} にソフトフォールバック)。i18n キー +18 ×17。テスト: tests/stats-funnel-route.test.mjs (+2)。スイート: 2481。

[1.184.0] — 2026-08-14

修正 (UI) — ダッシュボードのクイックアクションタイルが均等なグリッドで揃うようになりました。

修正

  • ダッシュボード(コマンドセンター)で、3枚のタイルのグループが4枚のグループより広く表示され、セクションの右端がガタついていました。各グループが等幅の列を使うようになり(広い画面で4列、ウィンドウが狭まると 3 / 2 / 1 に減少)、すべてのタイルが同じサイズで右端が揃います。

備考

  • CSS のみ(.qa-grid: auto-fill ではなく固定の repeat(N, minmax(0,1fr)))。tests/dashboard-grid-align.test.mjs でガード(+2)。スイート: 2479。

[1.183.0] — 2026-08-14

追加 (スキャナー) — より賢い重複検出: 追跡リンク付きで再掲載された同じ求人が二重に出なくなりました。

追加

  • スキャナーが求人を正規 URL キーで認識するようになり、追跡パラメータ(?utm_…、gclid など)付き、http と https の違い、末尾スラッシュ / #フラグメントで再掲載された同じ求人を、本来の1件として扱います — スキャン結果やパイプラインに重複行が出ず、既に見た求人の評価を無駄にしません。本当に異なる求人(gh_jid のような保持された機能的 id)は引き続き別個に数えます。

備考

  • 新しい server/lib/url-key.mjs を両スキャナーの dedup とパイプライン書き込みに接続。意図的に控えめに正規化し、異なる2件を決して統合しません。テスト: tests/url-key.test.mjs (+5)、tests/parsers.test.mjs (+1)。スイート: 2477 (+6)。

[1.182.0] — 2026-08-14

修正 (スキャナー) — 給与レンジがどの言語でも同じ表示になりました。

修正

  • スキャンとトラッカーの行の給与額が、英語の “from” / “up to”(非英語 UI に未翻訳で漏れていた)ではなく、ロケール中立の記号 ≥ と ≤(例: ≥ 120000 EUR、≤ 90000)を使うようになりました。片側レンジを返す全ボード(Getro、Remotli、Manfred、Agentic Jobs、JustJoin、Jobicy)に適用。両側レンジ(100000–150000 USD)は元から中立でした。

備考

  • 表示のみ。クライアントの給与フィルターは接頭辞に関係なく数値を解析するため、絞り込みは不変。スイート: 2471。

[1.181.0] — 2026-08-14

追加 (スキャナー) — Getro の求人ボードが給与・全ロケーション・リモート求人を表示するようになりました。

追加

  • Getro スキャナー(ファンドのタレントネットワークボード)が、各求人に給与(年額レンジ + 通貨)を表示し、最初の1件だけでなく全ロケーションを一覧化し、リモート求人にタグを付けるようになりました。スキャンとトラッカーの Getro 求人が、他のボードと同じ給与 + ロケーション情報を持つようになります。

備考

  • スキャナーのみ。新しい依存関係なし、ルート / CSP / SSRF の変更なし。テスト: tests/sources-getro.test.mjs (+5)。スイート: 2470 (+5)。

[1.180.0] — 2026-08-14

修正 (中, レポート) — #/reports 一覧がテーブルになり、Machine Summary のプレースホルダーが隠していた実スコアを復元します。

修正

  • #/reports 一覧は 4カードのグリッドではなくテーブル(レポート · 日付 · 信頼性 · スコア)になりました。 長い「スコア未検出」チップがタイトル列をほぼゼロまで押し縮め、カードタイトルの overflow-wrap: anywhere がレポート名を1文字ずつ改行していました。各フィールドが独自の列を持ち、名前セルは単語単位で折り返し、狭い画面ではテーブルが横スクロールします(新しい .reports-scroll コンテナ)。新しい i18n キー rep.colReport ×17。
  • 本文の実スコア(**Итоговый балл:** 1.8 / 5)が Machine Summary のプレースホルダー(score: —)に隠されなくなりました。 ## Machine Summary ブロックに数値でない、または範囲外のスコアがあると、解析済みスコアの枠を占有して太字の値形式フォールバックを妨げ、本文に実際の X / 5 があってもレポートは「スコア未検出」と表示されていました。parseReportHeader は、使用可能な数値が残らない場合に本文の値形式を復元します(ステップ4.5)。

備考

  • クライアント + パーサーのみ。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/reports-table.test.mjs (+5)、tests/report-header-locale.test.mjs (+2)。スイート: 2465 (+7)。

[1.179.0] — 2026-08-13

変更 (LOW, スキャナー) — 重複した 20 個の HTML エンティティデコーダーを共有モジュールに統合(パリティのフォローアップ、ワークリスト完了)。

変更

  • 20 のスクレイピング系スキャンソースが各自 decodeEntities/decodeXmlEntities(+ fromCodePoint ヘルパー)を持っており、これらのコピーはドリフトしていました(3 つは RangeError を投げ得た、v1.172.0 で修正済み。他は NUL/C0 を許容、または &#1a2; を誤解析)。今はすべて単一の server/lib/html-entities.mjs(XML 1.0 Char 安全なデコーダー)を通り、~237 行の重複を削除しました。8 つの RSS 系ソースは &nbsp; のデコードを獲得(以前は 5 種のみ)、cryptocurrencyjobs の意図的な二重デコードは別名で保持。hh は自前デコーダーを維持(&mdash;/&ndash; を扱う、共有 6 種の外)。新しいガードテストは、いずれかのソースがローカルデコーダーを再生成すると失敗します。

備考

  • 動作保存のリファクタリング。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/decoder-consolidation.test.mjs (+2)。スイート: 2458 (+2)。

[1.178.0] — 2026-08-13

修正 (LOW, 親パリティ) — 古い定数 2 つを親に合わせて更新(PARENT-SYNC GAP #4 + #5)。

修正

  • ブラウザ User-Agent (GAP #4) — BROWSER_LIKE_USER_AGENT(workable/workday/oraclecloud/a16z/eightfold が WAF/ボットゲート通過に送信)を Chrome 131 → 151 に更新し、親の user-agent.mjs に合わせました。古いビルドは弾かれやすいためです。Chrome major ≥ 151 テストで保護。
  • トラッカー状態 FALLBACK (GAP #5) — states.mjs の最終手段 FALLBACK(ライブの templates/states.yml が読めないときのみ使用 — 新規クローン / CI 分離ルート)に親のトルコ語ステータス別名(#2615)を追加: değerlendirildi, başvuruldu, yanıt verildi, mülakat, teklif, reddedildi, iptal edildi, uygun değil, kabul edildi/işe alındı。本番ではライブファイルが既に提供していました。

備考

  • 定数 2 つのみ。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/http-json.test.mjs (+1) + tests/states.test.mjs (+1)。スイート: 2456 (+2)。

[1.177.0] — 2026-08-13

修正 (MEDIUM, スキャナー) — 検索 API をセッションクッキーで保護するテナントで csod(Cornerstone)が 0 件を返していた(parent #2769、PARENT-SYNC GAP #1)。

修正

  • 一部の Cornerstone テナントはブートストラップの採用サイトホームでセッションクッキーを設定し、それが匿名ベアラートークンと共に戻らないと検索 API で 401 CSOD Unauthorized を返します。sources/csod.mjs は新しい fetchResponse ヘルパーでブートストラップを読み、Set-Cookie 値から Cookie ヘッダーを組み立て(cookieHeaderFrom — name=value のみ、jar セマンティクス)、検索 POST に再送します。同一オリジンのみ(ホスト固定 + redirect:'error')なので、セッションクッキーが第三者に届くことはなく、クッキーを設定しないテナントは従来どおり動作します。

備考

  • 新規 server/lib/http-json.mjs::fetchResponse(追加のみ。既存ソースに影響なし)。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/sources-parity-v1118a.test.mjs (+1)。スイート: 2454 (+1)。

[1.176.0] — 2026-08-13

修正 (MEDIUM, レポート) — RU 表にない太字ラベル下のスコアが依然 “Score not detected” と表示された(FIND-5)。

修正

  • 2 つの RU レポートはスコアを **Итоговый балл:** 1.8 / 5 / **Скор:** 1.8 / 5 と書いており、REPORT_LABELS.ru が列挙しない太字ラベル(“Оценка”/“Балл” のみ認識)のため未解析でした。同義語リストを増やす代わりに、parseReportHeader は 値の形にフォールバックします: 任意の太字ラベル下の /5 ルーブリックの分数。言語非依存で、見出しに免疫(** なし、/5 値なし)、5/5/2026 のような日付を拒否します(分母への否定先読み)。

備考

  • サーバーパーサーのみ。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/report-header-locale.test.mjs (+2)。スイート: 2453 (+2)。

[1.175.0] — 2026-08-13

修正 (LOW, 堅牢化) — FIND-3 の SEO 説明の回帰ガード + null 安全な正当性ストリップ(AI レビューのフォローアップ)。

修正

  • SEO 説明のパリティガード — 各言語の meta.desc のハードコード “~55” をレジストリ由来の {adapters} プレースホルダーに置き換えた v1.174.0 の修正にはテストがなく、次のロケール編集で静かに退行し得ました。新しい CI 分離テスト tests/site-meta-desc-parity.test.mjs は、17 個の site/src/i18n/*.json のいずれかがプレースホルダーを失う/件数を再ハードコードする、または Landing.astro が 3 つの説明メタへの差し込みをやめると失敗します。
  • null 安全な正当性ストリップ — stripEmphasis は null 入力に対して文字列 “undefined” ではなく '' を返します(フィールドは文字列で初期化されるため多層防御)。

備考

  • テスト + パーサーの 1 行ガード。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/site-meta-desc-parity.test.mjs (+3)。スイート: 2451 (+3)。

[1.174.0] — 2026-08-13

修正 (HIGH, レポート) — ローカライズされたレポートが “Score not detected” と表示され、SEO 説明が古かった。

修正

  • スコア解析 (FIND-1) — H1 にスコアラベル語を含む非英語レポート(# Оценка вакансии: <タイトル>)で、そのタイトルをスコアと誤認しなくなりました。parseReportHeader はローカライズされた太字ラベル(**Оценка:** 1.5 / 5)に固定し、見出し行をスキップし、ラベルがコロンに隣接することを要求します — これで “Score not detected” だった RU レポートが実際のスコアを表示します。
  • 正当性チップ (FIND-2) — 値から Markdown 強調を除去し、チップが “** High Confidence” ではなく “High Confidence” と表示されます。
  • スコアのはみ出し — 末尾にステータス文が付いたスコア行(“1.8, Status: Evaluated, …”)はスコアだけに圧縮されます。.score-pill に改行なし/オーバーフローの上限が付き、タイトル列が縮小できるため、色付きチップがカードの外にはみ出しません。
  • SEO 説明 (FIND-3) — cvstart.org の meta / OG / Twitter 説明(17 言語すべて)が “Scan ~55 job boards” を固定していた一方、本文は実レジストリ(“~75”)を数えていました。説明がレジストリ由来の数を差し込むようになり、再びずれません。

備考

  • サーバーパーサー + クライアント描画/CSS + サイト i18n。ルート / CSP / SSRF / 親書き込みの変更なし。テスト: tests/report-header-locale.test.mjs (+4)。スイート: 2448 (+4)。

[1.173.0] — 2026-08-13

追加 (LOW, 設定) — Hermes が検出対象の AI CLI 一覧に加わりました (career-ops パリティ)。

追加

  • #/config → 「AI CLI ツール」タブが、親プロジェクトが新たにサポートするエージェントランタイム Hermes(Nous Research、バイナリ hermes)を検出するようになりました。server/lib/routes/cli-detect.mjs の固定許可リストが 10 個から 11 個のツールに拡張されます。検出は読み取り専用の PATH スキャンのままです(バイナリは一切実行しません)。

備考

  • i18n / ルート / CSP / SSRF / 親書き込みの変更なし。一覧は固定の許可リストであり、入力ではありません。スイート: 2444(cli-detect カナリアを 10 → 11 に更新)。

[1.172.0] — 2026-08-13

修正 (MEDIUM, スキャナー) — 不正な HTML エンティティがスキャンソースをクラッシュさせ得た (career-ops #2150 パリティ)。

修正

  • oraclecloud・gem・dassault の各ソースは、数値 HTML エンティティを String.fromCodePoint の前に単純な Number.isFinite チェックだけでデコードしていました。0x10FFFF を超える参照(不正・敵対的なフィードの &#99999999; など)は捕捉されない RangeError を投げ、そのソースの解析全体を中断させました。共有モジュール server/lib/html-entities.mjs(親プロジェクトの _html-entities.mjs を反映)が数値参照を XML 1.0 §2.2 Char 集合に制限し、String.fromCodePoint が決して投げないようにし、16進と10進を別々にマッチするため &#1a2; が誤解析されなくなりました。3つのソースがこれをインポートします。

備考

  • 有効なフィードでは動作変更なし。JS / i18n / ルート / CSP / SSRF / 親書き込みの変更なし。残る約20個のソース内デコーダーコピーの統合は qa/PARENT-SYNC-WORKLIST-v1.26.0.md で追跡。
  • テスト: tests/html-entities.test.mjs (+7)。スイート: 2444 (+7)。

[1.171.0] — 2026-08-13

変更 (LOW, デザインシステム) — タイプスケール + z-index レイヤートークン(D-4、第一歩)。 サイズと重なりがコンポーネントごとにリテラルでした。

変更

  • z-index レイヤー — --z-* トークン(--z-topbar … --z-skiplink)を導入し、すべての z-index リテラルを移行。値は保持され、重なりは同一; 新しいカナリアがベアな z-index の使用を禁止します。
  • タイプスケール — --font-size-* ランプ(xs 11 … 2xl 28、base = Inter 15px)。コンポーネントが既に使っていた主要サイズを移行(見た目の変化なし)。ランプ外の値は段階的に移行(docs/UX-ROADMAP.md)。

備考

  • CSS トークンのみ。動作/JS/i18n/ルート/CSP/SSRF/書き込み変更なし。ピクセル変化なし。tests/design-tokens-scale.test.mjs(+3)。スイート: 2437 (+3)。

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