補足: 本記事は AI(Claude)が私の最初のメモと着想をもとに仕上げたものです。
前の二回は、一巡の作業がどう回るか、そして規律が守られたかをどう測るかの話だった。そのループを回し、その点数を計算しているものは、実のところ一つの git リポジトリだ。自身の README の数え方で、hook が百二十ほど、スキルが五十三、ルール文書が十九。
もう壊れるのに十分な大きさだ。この手の設定によく向けられる言い分は、hook にはテストがある、ルールには lint がある、一本の源が二つの runtime を描き出す、の三つだ。読み取り専用の調査エージェントを派遣して三つとも確かめた——結果、どれも半分しか合っていなかった。
結論を先に言う。製品として育てているのは、この三つの言い分がどれだけ正確かのためではない。壊れる前に、どう壊れるかを書いておいたからだ。この記事はまず三つの言い分を確かめ、それから本当にこれを支えているものへ移る。
これがいちばん事実に近い。hook のテストにフレームワークはない。手書きの check 関数が合否を数え、── N passed, M failed ── と一行印字する。テストファイルは hook の隣に置く。十二の hook を抽出したところ、七つにテストがあった。
あるものは、どれも実際に起きたことを釘で留めている。
書きながら小さな出来事があった。リポジトリを読ませるために派遣した調査エージェントが、リポジトリ自身の番人に門前で止められた——別のプロジェクトに根ざしたセッションはディレクトリを一覧することさえできず、ファイルを一つずつ読むしかなかった。番人が効いているかどうかは、思いがけず検証された。
だが「テストがある」は「関門がある」にはまだ届かない。CI がない。 テストは本物でよく書けているが、push でも merge でも何も走らせない。「hook にテストがある」の現在の意味は「誰かが走らせる」であって、「通らなければ入れない」ではない。
これは半分だけ正しい。レンダラはスキルの front matter に厳格で、許すのはちょうど二つの欄——一つ余れば、インストールは失敗する。これは本物の lint で、しかもインストールのたびに走る種類のものだ。hook 自体にも shellcheck の関門がある。
だが範囲は狭い。lint は shell の構文だけ、しかも変更したファイルだけを見る。 スクリプト自身が認めている。百ほどの hook は shellcheck が入る前に書かれ、全体を走らせれば古い指摘に溺れる。
本当に合っていないのは「ルール」という言葉のほうだ。ルールの散文自体には lint がない。 主設定は権限一覧に絶対パスを置くことを明文で禁じているが、守らせているのは審査時の判断であり、スクリプトではない。判断で執行されるルールは、それ自体が執行されていないルールだ。
確かめたなかでいちばん堅かったのがこれだ。一本のソースツリーが、Claude Code と Codex という二つの runtime の設定としてレンダリングされる。レンダリングとは複製ではなく書き換えだ。
/name → $name
AskUserQuestion → the structured user-input tool
model: sonnet → the appropriate current capability tier
~/.claude-personal → ~/.codex-personal
変換層もある。Codex のパッチ呼び出しはファイル単位の書き込みに翻訳され、同じ番人の hook が両側で無改変のまま走る。
最初は両方で動けばいいと思っていた。終えてから本当の価値が見えた。移植で壊れるものこそ、いつの間にか片方の runtime の形に育っていたものだ。 片側でしか成り立たないルールは、たいていルールではなく癖である。
副産物が一つ。二つの runtime は互いの記憶を見られないので、ワークフローの状態——ルーティング、好み、カーソル——は中立のディレクトリに置き、両側で共有する。ただしログインと会話履歴は共有しない。そして記憶のバックアップリポジトリを指すポインタは、意図的に記憶の仕組みの外に置いてある——記憶を立ち上げる役目を負うものは、立ち上げる対象の内側には住めない。
それでも両側は対等ではない。Codex 側は薄い。 コマンド昇格のポリシーは三つ、Claude 側の権限一覧は百五十ほど。
三つを確かめ終えて、これを製品らしくしているのは、実はどの言い分にも名指しされていない、いくつかの動作だ。
最初はいちばん地味で、いちばん重要だ。リポジトリが唯一の源であり、稼働中の設定ディレクトリはすべてその複製である。 インストーラは同じファイルをバイト単位でそのまま各ルートに置く。だから複製で読むルールは源で読むルールと寸分違わず、自分がどちらに立っているのか区別がつかないほどだ。
区別がつかないと事故が起きる。複製を直せば、次のインストールで静かに上書きされる。そこでルールには、誰が何を変えてよいかの表がある。
| 対象 | セッションが変えてよいか |
|---|---|
| プロジェクトの記憶ファイル | 自由に——記憶とはそのためのものだ |
| ルール文書、スキル | 提案し、言葉を待つ |
| 主設定、権限、hook | 提案に加えて影響範囲を名指しする——これらはすべての機械のすべてのセッションに読み込まれる |
| 稼働中の複製 | 決して触らない。次のインストールで上書きされる |
「影響範囲を名指しする」という欄が、製品的な考え方の出発点だ。自分しか使わないファイルであっても、どの行を変えれば全域に波及するかは区別できる。
二つ目は教訓がどうルールブックに入るかだ。事故のたびにルールを一つ足すのが、設定が腐るいちばんありふれた道だ。だから教訓には昇格の手順がある。まず記憶に落とす——安く、即座に、誰の承認もいらない。同じ誤りを二度正したとき、あるいは学んだプロジェクトの外でも通用するときにだけ、ルール文書へ昇格し、昇格そのものが提案になる。昇格したら、元の記憶はポインタに縮める。そして、その関心事を所有するファイルに落とす——スタイルのルールはスタイル文書へ、委任のルールは委任文書へ。どこかのスキルの本文に例外として縫い込むのではない。容れ物こそが要点だ。
三つ目は壊れ方を先に書いておくことだ。保守文書には「既知の劣化モード」という節がある。リポジトリ全体でいちばん製品らしい箇所だと思っている。これは壊れる、しかもどう壊れるかも分かっている、と認めているからだ。
五つ目には具体的な帰結がある。毎ターン注入される審査のリマインダーが名指しするのは「エージェントを派遣せよ」であって、「判決行を書け」ではない。行だけを促せば、モデルは行を打つことを覚える——リマインダーは、それが表す振る舞いより指標を満たしやすくしてはならない。
四つ目は従われることを拒む閾値だ。読み込まれる量には上限があるべきだ。旧版には三万五千字とあった。のちに保守文書は自らの数字を暴いた。それは何かから導かれたものではなく、書いた日のファイルの大きさだった(2026-07-08、実測 35,532)——予算の服を着た現状だ。新しい四万五千字は「臭いを嗅ぐための目安であって、上限ではない」と明記されている。超えたらファイルを読み、どのルールが重さに見合わなくなったかを問う。もし本当に当たったら、従うのではなく測り直す。
刈り込みは証拠で決め、字数では決めない。証拠は前回のダッシュボードから来る。量が 29,008 から 43,196 に増えるあいだに、全体の遵守率は 52% から 73% に上がった。文書はこれを「予想した害は現れなかった」と読む——そして「増やせば効く」とは読まないと明言する。同じ期間に分母が三度直されており、分母の修正はそれだけで率を押し上げるからだ。
同じ節には一度の失敗も記されている。ある刈り込みは 1,600 字の削減を見込み、実際は 371 字だった。節の大きさを測り、節の中の重複部分を測らなかったからだ。実際に消えるものを測ること。
三つの言い分とそれぞれの穴を、一つの表にまとめる。
| 項目 | 現況 |
|---|---|
| CI | ない——テストは人の規律であって、関門の規律ではない |
| lint の範囲 | shell の構文だけ、変更したファイルだけ;ルールの散文自体には lint がなく、絶対パス禁止は審査の判断に頼る |
| 二つの runtime | レンダリングは本物だが、Codex のコマンド昇格ポリシーは三つ、Claude の権限一覧は百五十ほど |
| リポジトリ内のセッション | 全体指示とプロジェクト指示がバイト単位で同一のまま、二重に課金される——文書自身の言葉では「解決ではなく記録」 |
既知の問題一覧を持つものは、それでも製品だ。持たないものは、趣味である。
これほど大きな設定は要らない。だがリポジトリなしでも持ち帰れるものが三つある。源は一つ、複製には決して触らない。壊れる前に、どう壊れるかを書く。そして、ある数字が書いた日のファイルの大きさにすぎないなら、そう正直に言う。