トップページの「情報」タブ (_layouts/home.html の grok-generated タグ絞り込み) に並ぶ記事は、
scripts/grok-post.mjs が Grok の応答を内容の精査なしにそのまま _posts/ へ書き出したものだった。
既存の検査はすべて体裁のみ:
書かれている内容が正しいかは一切見ておらず、末尾の「事実確認を行っていない」ラベルで免責していた。 これは親 #84 Decision Log #1「AI で裏付けをしない」(トークン節約と自立性を優先) に基づく 意図的な設計だったが、公開面の品質を優先して方針を転換する (issue #108)。
投稿前に DeepSeek API で記事を精査し、本文自体をリライトしてから _posts/ に書き出す。
Grok 応答 → sanitize → title/body 抽出
→ link-check.mjs : 本文全体の URL を HEAD/GET で生存確認
→ deepseek-review.mjs : 死リンク情報を添えて DeepSeek に精査・リライトさせる
→ findIntroducedUrls : 元記事に無い URL が増えていたらリライトを棄却
→ link-check.mjs : 公開される本文を再検査。死リンクが残っていれば棄却
→ renderPost(reviewed): ラベルと tags を精査の成否で切り替えるdeepseek-v4-pro 既定 (DEEPSEEK_REVIEW_MODEL で上書き可)pass から scripts/grok-post-run.sh が注入する
(参照先は DEEPSEEK_PASS_PATH 既定 knowledge-fabric/DEEPSEEK_API_KEY)--no-review で精査を切って従来動作に戻せるDeepSeek 呼び出しが失敗したとき (キー不在 / HTTP エラー / タイムアウト / 空 content / リライト結果が文字数レンジ外) は、Grok 原文+従来の「事実確認を行っていない」ラベルで投稿する。
ai-reviewed タグと末尾ラベルは
精査に成功した記事にだけ付き、読者が区別できる状態を保つ404 / 410 だけを死と判定する。403 (bot 遮断)・5xx (一時障害)・タイムアウト・DNS 失敗は
「判定不能」として死リンク扱いしない。生きている URL を誤って削除させる方が害が大きいため。
さらに、死判定は必ず GET で確認してから確定する。HEAD を未実装のまま 404 を返し
GET なら 200 を返すサーバーが実在し、HEAD だけで確定すると生きた出典を記事から
消してしまう。GET が届かなかった場合も「判定不能」として死リンク扱いしない。
link-check.mjs が決定論的に確認して補う。rengotaku.github.io/DEEPSEEK_API_KEY を新設: 秘密を複製すると
ローテーション時に片方が取り残される。既存エントリを参照し、パスは env で差し替え可能にした。DEEPSEEK_REVIEW_MODEL)、MAX_COMPLETION_TOKENS、タイムアウト値buildUserPrompt)DEAD_STATUSES)RETRY_DELAYS_MS)DEEPSEEK_PASS_PATH)reviewed フラグとラベル・tags の対応。精査していない記事に精査済みラベルが付くと、
読者に対する虚偽表示になる (この ADR の存在意義そのもの)reviewAndRewrite() が例外を投げないこと。投げると 1 記事の精査失敗が
その日の投稿全体を落とすextractTitleAndBody の例外を汎用 catch に落として通信断と同じ扱いにする穴を踏んだonRetry / sleep の例外を外へ出さないこと (#115)。リトライの通知や待機が
失敗しただけで例外が伝播すると、上の「例外を投げない」契約が破れてその日の投稿が
丸ごと落ちる。onRetry は await して呼ぶこと — async コールバックの rejection は
await しないと try/catch をすり抜け、unhandled rejection でプロセスごと落ちるchoices[0].message.content からのみ取ること。DeepSeek v4 系は reasoning
モデルで、reasoning_content には思考過程が入る。混ぜると記事に独り言が載るmax_tokens が不足すると finish_reason: "length" で
content が空のまま返る (実測)。空を採用すると記事が消える参考 行で返す・DeepSeek が URL を節の外へ動かす・見出しを変える、の
いずれでも検査が素通りする (#108 では実際に全記事で 0 件になりサイレントに無効化された)。
本文全体の URL を対象にすることで、見出し表記への依存ごと無くしてあるhttps://…/Foo_(bar) を …/Foo_ まで
しか取らないと、切断点より後ろを書き換えられても混入検出をすり抜け、リンク検査も
別物 (切り詰めた URL) を叩く。閉じ括弧は開き括弧とのバランスで判定する