トップページは記事を「記事 / メモ / 情報」の3タブに振り分けている。この分類を過去に2回、一括で付け直したが、いずれも取りこぼしを残した。
| 回 | 対象 | 基準 | 取りこぼす理由 |
|---|---|---|---|
| 1回目 (#105) | 直近3ヶ月の68件 | LLM 判定 | 範囲が3ヶ月に限定され、それ以前が対象外のまま残った |
| 2回目 (#113) | 全件 | 地の文200字以下 | 文字数は「記事らしさ」の代理指標。設定・コード主体のメモは地の文が伸びて素通りする |
例として _posts/2018-04-17-sublime3.md(エディタの導入手順と設定ファイルの羅列)は地の文380字・コードブロック3個のため200字基準を超え、記事タブに残っていた。内容は完全に手順メモである。
根本原因は分類の既定値が「記事」だったことにある。type を書き忘れた記事は静かに記事タブへ入るため、漏れが漏れとして観測できない。一括分類を何度やっても取りこぼしが累積した。
作業中、同じ性質の fail-open が他に2箇所見つかった。
scripts/check-post.sh は Go 製バイナリ(tools/check-post)があればそちらに exec する。シェル側の Python だけに検査を足しても、実際には検査が効かない.github/workflows/validate-posts.yml は ./scripts/validate-posts.sh || true で呼んでおり、検査がエラーを報告しても CI は緑のままtype(article / memo / info)を全記事の必須 frontmatter キーにし、未指定・値域外・空値を検出したら失敗させる。判定基準は docs/post-classification.md に成文化する。
漏れを止める層は4つ。
| 層 | 実体 | 何を止めるか |
|---|---|---|
| 値 | type が全記事必須 |
未指定が既定で記事タブへ落ちること |
| ローカル検査 | tools/check-post の Rule 10 / 10b |
執筆時点での未指定・値域外・空値 |
| CI | validate-posts.yml の Validate post classification step |
_posts/** を触る PR での未指定 |
| 再判定 | scripts/classify-posts.py |
基準変更時に全件を測り直せない状態 |
付随する決定:
classify-posts.py は未分類の検出(--report / --validate)と判定結果の一括適用(--apply)だけを担い、記事かメモかの判断はしない|| true を付けない。同 workflow の validate-posts.sh に相乗りさせると失敗が job に伝播しないtype の値の取り出しは3実装(Go / classify-posts.py / check-post.sh の fallback)で同一規則にする。クォート付きは閉じクォートまで、無しは空白に続く # まで_layouts/home.html)は変更しない。type は分類の明示と CI ゲートのために持つsublime3 のようにコードが多く地の文が伸びる型は閾値を上げないと拾えず、上げると論考のある短い記事まで巻き込む。実際、既存メモ222件のうち30件は論考があり記事へ是正した。代理指標を調整し続ける限りこの誤りは消えないpublished: false の下書きを検査対象から外す — Jekyll のビルド対象外でも分類は必要(公開時に漏れる)。実際に4件が該当し、いずれも type を付けてあるtype の値域に第4の値を足すこと(3実装の validTypes と docs/post-classification.md を同時に更新する)。判定を誰が行うか(人 / AI / 別ツール)。classify-posts.py の TSV 形式validate-posts.sh 側へ統合すること。あちらは || true で呼ばれているため、統合した時点でゲートが無効化されるclassify-posts.py に自動判定を実装すること。機械判定は代理指標に戻ることを意味し、この ADR の前提そのものを崩す