フレームワーク作者がフレームワークを破ったとき: v1.1.0 → v1.2.0 の自社監査
これは自社監査シリーズの2本目のケーススタディである。1本目 はフレームワークの上に構築された2つのプロダクトサイトを扱った。本作は、フレームワーク自身が定義した規則を直後の自身のリリースで破った、その瞬間を扱う。
この記事を書く3日前、私たちは LLMO フレームワーク v1.1.0 をリリースした。見出しは新しい第6コンポーネント 整合性シグナル — AI エージェントが読むあらゆる面で同じ事実が同じ物語を語ることを保証する規律 — の追加だった。
このコンポーネントの中核主張:
すべての数値・事実主張に対して、他のすべての場所から参照される単一の正規ソースファイルを持つ。
2日後、v1.2.0 をリリースした — 既存コンポーネントの下に2つのパターン(Identity-as-Code、Citation Preferred)を追加。バンプは手動だった: 開発者が package.json を version: "1.2.0" に書き換え、コミットメッセージを書き、push した。
v1.2.0 の状態に対して codex で第2段レビュー を実行したとき、考えうる最大の皮肉が筆頭で返ってきた:
/llms.txtが「5 components / 15 points」のまま だが、サイトの他の部分は新しい第6コンポーネントを広告している。
整合性シグナルを定義したサイトが、その概念を導入したまさにそのリリースで、サイトのもっとも主要な AI 可読面の上で整合性シグナルを破っていた。
LLMO の意味において、バージョンは事実である。「フレームワークは v1.2.0 にいる」という事実は、1つの正規主張であるべきだった。v1.2.0 リリースコミットでは、それが5箇所に存在し、しかも一致していなかった:
| 面 | 状態 | 経緯 |
|---|---|---|
package.json | 1.2.0 ✓ | 手動編集 |
src/data/version.ts | 1.1.0 ✗ | 未触れ |
CHANGELOG.md | [1.1.0](v1.2.0 エントリ無し) ✗ | 未触れ |
src/content/docs/changelog.md(EN) | v1.2.0 ✓ | 手動編集 |
src/content/docs/ja/changelog.md(JA) | v1.1.0(v1.2.0 エントリ無し) ✗ | 未触れ |
| Git タグ | v1.1.0(v1.2.0 無し) ✗ | 失念 |
加えて、バージョンドリフトの下流として、8 言語の /llms.txt のコンテンツドリフト — どの言語版も新6番目コンポーネントや Two-Pass Review ガイドや Self-Audit ケーススタディを反映していなかった。
6 つの面、3 つの異なる物語。package.json を引用する AI は v1.2.0 の新パターン入りを返す。llms.txt を引用する AI は v1.0.0 形状の5コンポーネント・フレームワークを返す。changelog ページの英語版を見る AI は v1.2.0 を見るが、日本語の読者は v1.1.0 を見る。サイトは自分自身と矛盾していた。
なぜ起きたか
Section titled “なぜ起きたか”私たちは /bump-llmoframework skill と scripts/bump-version.sh を書いた。両者は5つの面のうち3つ(package.json、src/data/version.ts、CHANGELOG.md)を原子的に更新する。残り2つ(changelog.md EN/JA)を Phase 3 の一部として更新するよう、明示的にオペレーターに指示する。
v1.2.0 ではどちらも使われなかった。リリースは直接編集 + コミット + push で起きた。
整合性を強制するはずの仕組みがバイパスされ、整合性を監視する面(フレームワークサイト本体)が、リアルタイムで「バイパスのコスト」を実演した。
ここに悪意も不注意もない。これは1つのルールの予測可能な結果である:
整合性面が手で保守されている限り、いずれその手は忘れる。
bump スクリプトとスキルは、まさに手が忘れるからこそ存在する。それらをスキップすると、あなたはフレームワークを読んでいる全員にとっての整合性テストケースになる。
read-only 状態の codex exec を v1.2.0 リポジトリに対して起動し、プロンプトで 「v1.1.0 リリース成果物と実際のデプロイ状態の整合性」 を明示的に問うと、こう返ってきた:
最大の皮肉: 新設された Coherence Signals コンポーネントが
/llms.txtとバージョンファイルの上で違反されている。次のリリース前に修正することを推奨する。
実時間: 約4分。関連コマンドは LLMO監査: 二段レビュー に文書化されている — まさに v1.1.0 で導入したばかりの記事だ。
修正(v1.2.0 cleanup としてコミット)
Section titled “修正(v1.2.0 cleanup としてコミット)”| ステップ | 面 | 変更 |
|---|---|---|
| 1 | src/data/version.ts | VERSION = '1.2.0'、新しい RELEASES[0] エントリ(summary + 4 つの highlights) |
| 2 | CHANGELOG.md | フル v1.2.0 セクション(Headline / Added / Changed / Why)+ compare リンク |
| 3 | src/content/docs/ja/changelog.md | フル v1.2.0 セクションを日本語で、英語版と並列に |
| 4 | src/content/docs/changelog.md(EN) | v1.2.0 セクションを CHANGELOG.md と同じ密度に拡張 |
| 5 | public/llms.txt(8言語) | 6 components / 18 points に更新。Coherence/Two-Pass/Self-Audit/Changelog のエントリを追加 |
| 6 | public/ai/*.md(8言語) | 同じ更新。正規ホストの正規化、数値をプロファイルデータに揃える |
| 7 | Git タグ | v1.2.0 annotated タグを作成して push |
| 8 | src/components/Footer.astro | 新規: 全ページに v{VERSION} · Changelog を表示。src/data/version.ts から読む。バージョンが人間に見える状態になり、メタデータの中に埋もれない |
| 9 | scripts/verify-json-ld.mjs | 新規: npm run build 後に走る CI ゲート。JSON-LD のパース、全ページに サイト全体 Organization/WebSite/Person、404 ページに article 系スキーマが無いことを検証 |
| 10 | .github/workflows/deploy.yml | デプロイ前に verify-json-ld ステップを追加。次回、構造化データが壊れた状態でリリースを試みると、GitHub Actions が公開前に失敗する |
ステップ10 のあと、サイトは codex 第2段レビューを再走行しても release coherence に関する P0 発見は出ない状態になった。
このエピソードが整合性シグナルについて語ること
Section titled “このエピソードが整合性シグナルについて語ること”ここから3つのパターンが一般化できる:
1. リリースプロセス自体が整合性面である
Section titled “1. リリースプロセス自体が整合性面である”バージョン番号は事実だ。1箇所を更新して5箇所のうち4箇所を更新しないリリースは、stale な llms.txt と同じくらい本物の整合性違反だ。リリースパイプラインはフレームワークのコンテンツ面の一部であり、それと別物ではない。 自身のリリースプロセスを考慮しない整合性フレームワークは、リリースのタイミングで失敗する。
2. ツールはバイパスされたときに価値を証明する
Section titled “2. ツールはバイパスされたときに価値を証明する”bump-version.sh スクリプトと /bump-llmoframework スキルは、手動バンプがドリフトするからこそ存在する。v1.2.0 のドリフトは、まさに両方がバイパスされたから起きた。ツールをスキップしたコストは、最も公開的な形で支払われた: 整合性を定義するフレームワークが、それを破った場所だった。
これはツーリングの失敗ではない。スクリプトを v1.1.0 に対して走らせていれば、整合的な v1.2.0 が生成されていただろう。失敗は package.json を直接編集するという人間の判断にあった。修正は、よりよいツールを書くことではない — 手動経路をうるさくすること だ:
- フッターに
v{VERSION} · Changelogが全ページに表示されるようになった。package.jsonとsrc/data/version.tsのドリフトは、npm run buildで生成される全ページの下部で即座に可視化される - CI ゲートがデプロイ前に
verify-json-ld.mjsを走らせる。スコープやパースの違反が production に到達できない - bump スクリプトの idempotency ガードが、既存のバージョンセクションや git タグへの再走行を拒否する。以前ドリフトを隠していた重複セクションのバグが防がれる
一般則: 手動経路が存在する限り、ビルドのたびにドリフトを浮き彫りにするフィードバックを与える。
3. フレームワークは作者を免除しない
Section titled “3. フレームワークは作者を免除しない”最も居心地の悪い学びは、最もシンプルだ。整合性シグナルをフレームワークコンポーネントとして提案したチームが、それを導入したリリースで整合性シグナル違反を出した。v0.x で足元を探っていた段階ではない — v1.2.0、ルールが書きたて、スキルとスクリプトが既に整備された状態で、だ。
フレームワークを実装することと、フレームワークに従うことは、別の認知行為である。
前者は概念形成の筋肉を使う。後者は規律の筋肉を使う。フレームワークの作者は、しばしば概念形成の筋肉が並外れて発達し、規律の筋肉は普通である。外部の観察者 — 第2段レビュアー、read-only サンドボックスの AI エージェント — は概念形成のコンテキストを持たないが、規律はあらゆるページに対して一様に効く。
これがフレームワーク自身のサイトに二段レビューが任意でない理由だ。指を切った医者が同僚に診せに行くのと同じ理由である。
LLMO を実装する人への教訓
Section titled “LLMO を実装する人への教訓”この問題を相続するのにフレームワークを書く必要はない。複数の AI 可読面(HTML / Markdown / JSON-LD / llms.txt / API レスポンス / ドキュメントサイト)を持ち、何らかのリリースケイデンスを持つ組織はすべて、人間が独立にそれらの面を保守する限り、同じドリフトを生む。
レバレッジ順に、実用的なステップ:
- 整合性面を明示的に列挙する。多くのチームは、1つの事実が何箇所に存在するかを把握していない。書き出す
- どの面が自動生成で、どれが手動かを特定する。手動こそドリフトの発生源
- 最小限の正規事実セット(バージョン、ヘッドカウント、主要URL、ブランド命名)について、可能な限り多くの面を1つのソースから生成する。
src/data/*.tsを読んで手動ファイルを emit する50行の Node スクリプトでも、1リリースサイクルで元が取れる - 手動のままでなければならない面については、リリースをクロスチェックでゲートする。不整合を grep して非零で exit する
make verify-coherenceステップが、人間の目が見落とすものを捕える - マイナー以上のリリースごとに read-only AI 第2段レビューを走らせる。コスト: API トークン数セント〜低数ドル。便益: 皮肉が live になる前に捕まえる
- フレームワーク作者であってもフレームワークから免除されないことを受け入れる。ゲートは作る
追記 (v1.3.1): 6つ目の面
Section titled “追記 (v1.3.1): 6つ目の面”このケーススタディは v1.3.0 で公開された当初、バージョンドリフトの5つの面を主張していた: package.json、src/data/version.ts、CHANGELOG.md、EN/JA changelog ページ、git タグ。公開から1時間以内に、ken がライブサイトを読みながら指摘した — ヘッダーがまだ v1.0 と表示されている、と。
ヘッダーは src/styles/custom.css に CSS pseudo-element (.site-title::after { content: 'v1.0' }) としてハードコードされていた。プロジェクトの初コミットからそこにあり続けていた。v1.0 → v1.1 → v1.2 → v1.3 — 4 リリース、4 バージョン、CSS には誰も触れなかった。フッターは v1.2.0 で src/data/version.ts から読むよう追加され、可視バージョン表示の正規ソースとなった。ヘッダーの CSS バッジは気づかれず、視覚レイヤーに住んでいて、バージョン管理のメンタルモデルに入っていなかった。
実際の数は5ではなく6だった。5つは同期され、1つは忘れ去られていた — しかも全ページの目に見える場所に。
v1.3.1 の修正は、CSS pseudo-element を完全に削除すること。フッターが今や唯一の可視バージョン情報のソースだ。次の保守者が別の形で再現しないよう、custom.css にコメントが削除を文書化している。
教訓は一般化される:
同じ事実の面は、いつも自分が予期した場所に存在するわけではない。 バージョン番号は JSON、TypeScript、Markdown、git タグ、YAML frontmatter — そして CSS の
content:プロパティの中にも住みうる。「この事実が住む場所すべて」を列挙するときは、データ層だけでなく視覚層も含める。ユーザーにテキストをレンダリングするものはすべて面である。
ken は、5つを閉じたと自慢する v1.3.0 のページを読む時間で、6つ目の面を捕えた。これはフレームワークの失敗ではなく、フレームワークが機能している証拠だ。すべての整合性面を見つけたと確信する唯一の方法は、自分の列挙を公開し、他の読者が見落としを見つけてくれるのに任せることだ。
このケーススタディを導入する v1.3.0 の作業は、整合性シグナル に新しいサブセクション 「リリースプロセスは整合性面である」 を追加し、教訓を一般化する。
フレームワークは完成していない。すべてのリリースが、前回のリリースが見えなかったものを暴く — ときには、前回のリリースが出てから1時間以内に。
- LLMO監査: 二段レビュー — これを捕えた方法論
- 整合性シグナル — 違反され、その後に強化された原則
- Propel-Lab リファレンスサイトの自社監査 — 1本目のケーススタディ。本作はそのパターンを継続する
- 変更履歴 — この記事が描写する実際のバージョン履歴