「受け入れた」は品質の証拠にならない。残存率という指標を手元のリポジトリで数えた

VS Code のブログに「MAI-Code-1-Flash: early results from real developer workflows」という記事が出ました(2026-07-29 公開、2026-07-30 取得)。新しいコーディングモデルのローンチ記事なのですが、目を引いたのはモデルの性能ではなく、性能の測り方のほうでした。 AI が書いたコードの評価に、受け入れたかどうかではなく、後から見てまだ残っているかを使っています。言いたいことを先に図にすると、こうです。 提案 受け入れる その後さわる コミット 受容率 ここで測定が終わる。材料は差分と、読んだ数十秒だけ 残存率 残存率は、動かして落ちた・読み返して消した … 受容の時点には無かった材料で決まる 測る区間が違うから、2つは逆を向くことがある 元記事の実測: 受容率 −6% のモデルが、残存率 +4% / コミット時残存率 +6%(baseline 比) 受容率は「読んで通したか」、残存率は「後から消さなかったか」。判定する材料も、判定する時点も違います。 ...

August 18, 2026 · nnasaki

エージェント運用をグラフとして設計する。14段ロードマップの主張を2つ、手元で実測した

0xMovez AI さんの「Graph Engineering with Claude: 14-Step roadmap from 0 to graph architect」(2026-07-25 公開、2026-07-30 取得)を読みました。直線的に走らせているエージェント運用を、処理の単位(節点)とデータが流れる経路(辺)からなるグラフとして設計し直す、という記事です。 主張のうち2つを手元の環境で実際に動かして確かめたので、その結果まで書きます。 記事が言っていること 14段の構成です。前半は基礎(節点は1エージェント1ジョブ、辺は実際にデータが流れる依存だけ)、中盤は型(並列展開、全部揃ってから進む待ち合わせ、展開→縮約→統合のダイヤモンド、辺の上に検証者を置く)、終盤が今回試した2つです。 Step 12(節点ごとにモデルを階層化する): Not every node needs your best model. (中略) Run the boring nodes on a cheaper model and spend your expensive tokens where judgment actually lives. 〔訳〕すべての節点に最良のモデルが要るわけではない。退屈な節点は安いモデルで走らせ、高価なトークンは判断が実際に住んでいる場所に使え。 Step 14(良い実行を再実行可能な定義として保存する): When a run is good, press s to save its script into .claude/workflows/ - version-controlled, re-runnable by name, a graph anyone who clones the repo can launch. ...

August 18, 2026 · nnasaki

エージェントに「なんで?」と聞くのをやめて、作業のときに書かせる

エージェントが妙な変更をしたとき、「なんでこうしたの?」と聞いている人向けです。返ってくる答えが何なのか、代わりにどこを読めばよいのかを書きます。あわせて、手元の Claude Code のセッションログに思考の中身が残っているかを数えたので、そのコマンドと出力をそのまま載せます。 きっかけは X の投稿です。そこで挙げられていた理由(thinking が直近ターンしか文脈に入らない)は、公式ドキュメントに当たるとモデルによって違いました。ただし、どちらのモデルでもやることは変わりません。なぜ変わらないのかまで書きます。 まとめ エージェントに「なんで?」と聞くのをやめます。代わりに、依頼するときに「変更ごとに、その根拠を1行で添えて」と書いておいて、あとでその記録を読みます。理由は、聞いてから作らせるのではなく、作業した時点で書かせるほうが確かだからです。 聞いて返ってくる説明は、そのとき作られたものです。ヒントを与えて答えを変えさせた実験で、そのヒントを使ったと自分で書いたのは 25% でした(Claude 3.7 Sonnet での測定。新しいモデルで同じ数字になるとは限りません)。 Claude Code を使っているなら、自分のセッションログを開いてみてください。既定では、考えた形跡だけがあって中身が空です(数えたら 6,319 個すべてが 0 文字でした)。設定を入れると、画面で対話しながら進めた分は残ります。-p を付けて実行した分は残りません。 ⚠ 「セッションログ」「思考」「対話モード」が何を指すかは、本文で順に説明します。まとめだけで分からなくても、読み進めれば分かるようになります。 きっかけの投稿 もとは、LLM に理由を尋ねたときの応答についての投稿です(@golden_lucky、2026-07-30 投稿、2026-08-15 取得)。 「なんでこうしたの?」ってLLMに言うと「すみません考えが足りませんでした」みたいなこと言ってくるけど、そうじゃなくて理由を聞いてるんだよ、理由を答えてくれよ、人間になるなよ これを引用して、原因と対策を述べた投稿がこちらです(@Hi_Noguchi、2026-07-31 投稿、2026-08-15 取得)。長いので要点だけ引きます。 少なくとも Claude についていうと、「なんで」かは Claude 側も「知らない」。というのも thinking の内容が直近ターンのものしかコンテクストウィンドウに入っていないため。 なので Claude は過去の自分のアウトプットだけを見て、事後推測するしかないというわけ。だからそれっぽい「ウソ」ついたりする。 対策として、showThinkingSummaries を有効にしてセッションログ(jsonl)に記録される thinking summary を振り返らせること、その自動投入先として DuckDB や hooks が挙げられています。 言っていることには納得しました。理由を聞く相手を、エージェント本人から記録へ移すという話です。そのうえで、記録に何がどう入るのかを確かめました。 エージェントとのやりとりで、思考はどう扱われているのか 1回目と2回目に、何が行き来しているのか 先に用語を分けます。この記事で「説明」と呼んでいるのは、あとから「なんで?」と聞いたときに返ってくる文章のことです。モデルが答える前に内部でやっている推論のほうは「思考」と呼び、API では thinking ブロックとして扱われます。別物です。 以下は Anthropic の Extended thinking(2026-08-15 取得)に書かれている API の挙動です。Claude Code のようなハーネス越しに使っているときも、下ではこのやりとりが起きています。 ...

August 15, 2026 · nnasaki

エージェントハーネスの grep は grep ではなかった。「0件でした」を信じていたら、本文は全文入っていた

エージェントに調べ物をさせて、その結果を信じてよいか確かめている人向けです。 「原文を取ってきて、この語句を grep して件数を報告せよ」という指示は、裏取りのやり方としてかなり筋がよく見えます。実際、私はそれを規約に書いて1週間ほど運用していました(明文化したのは 2026-07-26 です)。その規約が破れたので、破れ方と直し方を書きます。手元で最小再現まで取れたので、コマンドと出力をそのまま載せます。 先にまとめです。 エージェントハーネスは、あなたが呼んだつもりのコマンドを別物に差し替えていることがあります。 私の環境で grep を呼ぶと、それは GNU/BSD の grep ではなくシェル関数で ugrep -I に差し替わっていました(Claude Code 2.1.220 / macOS / zsh、2026-08-02 時点)。-I はバイナリ扱いのファイルを飛ばすオプションで、NUL バイトが1個でもあると、何も出力せず終了コード1 を返します。grep -c が出すはずの 0 すら出ません そして grep -c が数えているのは行数であって出現回数ではありません。圧縮された1行の HTML では、何を探しても件数が 1 になります この2つが重なった結果、サブエージェントが「本文は取得できていません(ヒット0件)」と報告してきました。実際には本文が全文入っていました 差し替えの中身はハーネスごとに違うはずですが、「自分が指定したコマンドが、その名前どおりのものとは限らない」という形は、どのハーネスでも同じだと思います。以下、私の環境での実測です。 なぜ「件数を報告せよ」にしていたか 先に背景を書きます。読み飛ばして構いません。 エージェントに文章を書かせると、もっともらしい嘘が混ざります。厄介なのは、書いた本人にそれが検出できないことです。自分の出力を自分で検算しても、生成したときと同じ経路をたどって同じ結論に戻ります。 そこで「書く人」と「原典に当たり直す人」を分けて、後者には次の形で報告させていました。 該当句を生 HTML に対して grep -c し、ヒット数を報告せよ。バイト数は同一性の証明にならない(動的サイトはリクエストごとに揺れる)。 バイト数を退けているのは、それが証拠にならないからです。同じ URL でも日をまたぐと変わります。 $ U=https://x.com/kimuai08/status/2082428727401869753 $ curl -sL -A 'Mozilla/5.0' "$U" -o x.html -w '%{size_download} bytes\n' 362384 bytes 2026-08-02 取得です。前日 2026-08-01 に同じコマンドで取ったときは 362,678 バイト、同日に User-Agent を Chrome のものに変えたときは 367,448 バイトでした。どれも「取れた」のに、数字は一致しません。 だから「その語句が原文に在るか」という形の証拠、つまり grep の件数に寄せていた、という経緯です。 ...

August 15, 2026 · nnasaki

CLAUDE.md のどの行を消してよいか、ビルドの Red/Green で決める

CLAUDE.md や AGENTS.md、copilot-instructions.md が膨らんできて、削りたいが怖くて削れない人向けです。 削ってよい行を、勘ではなく CI の終了コードで判定する方法を書きます。手元のリポジトリで9通り実測したので、その手順と結果をそのまま載せます。 以下、規則違反を検出して CI を落とす自動検査(lint、ビルド時の検査、生成物の検査など、種類は問いません)を 「ゲート」 と呼びます。この記事の話は結局のところ、文書に書いた規則と、ゲートが見ている規則の、重なりを測るというだけのことです。 ⚠ もう1つ先に読み方を。この記事の RED/GREEN は、いつもの「ビルドが通った/落ちた」ではありません。 わざと違反を仕込んだ状態で CI を回すので、向きが裏返ります。 いつもの CI この記事 RED まずい ゲートが仕事をした GREEN よい 誰も見ていない TDD で、実装を書く前にテストを一度 RED にして「このテストはちゃんと落ちる」と確かめるのと同じ向きです。赤くならないテストが無意味なのと同様に、破っても GREEN のままの規則は、機械には存在していません。(コードの世界では mutation testing——わざと壊したコードにテストを当てて、ちゃんと落ちるか確かめる手法——と呼ばれているものを、命令文書に当てているだけです。) たとえるなら、CLAUDE.md の一行は「ドアを閉めること」という張り紙で、ゲートは開けっぱなしを検知する警報装置です。この記事でやるのは、張り紙を剥がしてみて様子を見ることではありません。 張り紙(文書の規則)を1つ選ぶ。まだ剥がさない 張り紙が禁じていることを、コードのほうでわざとやってみる(確かめたら元に戻します) 警報(CI)が鳴れば RED。機械が見張っているので、張り紙は剥がせる 鳴らなければ GREEN。見張りは張り紙しかないので、剥がせない。先に警報装置を作る 順序が肝心です。先に張り紙を剥がしても警報の配線は何も変わらないので、鳴るかどうかの確かめにはなりません。剥がすのは、鳴ると確かめたあとです。 まとめ 判定はこれだけです。「その規則をわざと破ったとき、CI は気づくか」。 気づく(RED)なら機械が同じことを言っているので、文書の行は消せます(ただし、その規則を破る頻度が低いときに限ります。理由は後半に)。 気づかない(GREEN)は「文書に残す」ではありません。「ゲートの積み残し」です。 まずゲートを書けないか考え、書けないものだけを文書に残します。 手元では GREEN 4件のうち3件を実際に書けたので、CLAUDE.md から削除しました。最終的に 9件中8件が文書から消え、残ったのは1件です。 削れる行の割合は、文書の質ではなくゲートの本数で決まります。 8割削りたければ、先に8割を捕まえる機械が要ります。順序は逆にできません。 なぜこれを測ったか 「Claude Code のプロンプトの 80% を削った」と題した Claude Code 作者の動画が公開されました(YouTube、2026-08-07 取得)。ページの HTML には "uploadDate":"2026-07-27T10:00:30-07:00"、itemprop="duration" content="PT35M52S" とあります。同ページの説明文によれば、出演は Boris Cherny と Diana Hu、収録は Startup School 2026 です。 ...

August 7, 2026 · nnasaki

MCP がステートレスになった — リモートサーバを運用する側から見て何が変わるか

MCP の新しい仕様 2026-07-28 が出ました。告知の一文が「MCP is now stateless, making it easier to deploy and scale remote servers」です(@ClaudeDevs、2026-07-29 取得)。 リモート MCP サーバを自分で運用する側から読むと、これは仕様の話というより配置の話でした。実際に最小のサーバを書いて確かめたので、その結果まで書きます。 何が変わったか ステートレス化は3層にまたがっている changelog(2026-07-29 取得)を読むと、「ステートレス」が指しているものは1か所ではありませんでした。 セッション管理 — Mcp-Session-Id ヘッダがプロトコルレベルで削除されました。さらに initialize / notifications/initialized のハンドシェイク自体が無くなり、各リクエストが _meta に自分でプロトコル版とクライアント capability を載せます(io.modelcontextprotocol/protocolVersion、io.modelcontextprotocol/clientCapabilities)。 トランスポート — GET のストリームエンドポイントが削除されました。サーバが公開するのは POST を受ける単一エンドポイントだけです。SSE は「そのリクエストにスコープされたストリーム」としてのみ残り、Last-Event-ID による再開機能も削除されています。切れたら新しい request ID で送り直す、という規定になりました。 双方向性 — roots/list や sampling/createMessage のようなサーバ起点のリクエストは Multi Round-Trip Requests(MRTR)に置き換わりました。サーバは resultType: "input_required" を返し、クライアントが元のリクエストをリトライする際に応答を添えます。常時開いた双方向ストリームが要らなくなる、という形です。 かわりに server/discover が追加され、こちらはサーバの実装が MUST です。 図にするとこうです。左が従来、右が 2026-07-28 です。 従来(〜2025-11-25) 2026-07-28 クライアント サーバ initialize / initialized Mcp-Session-Id を発行 以後の全リクエストに Session-Id GET の常時 SSE ストリーム サーバ起点の要求(sampling 等) 両端が「どのセッションか」を 覚えている必要がある クライアント サーバ POST(単一エンドポイント) _meta に版と capability を自己記述 resultType: complete resultType: input_required 元リクエストをリトライ+応答添付 (MRTR: サーバ起点の代替) 接続をまたいで覚えるものがない。 SSE はリクエスト内のみ ハンドシェイク・セッション・GET ストリームがある 各リクエストが自己完結する ステートレス化「だけ」ではない ここが読み違えていたところです。changelog の major change は9件あって、破壊的なものが並んでいます。 ...

July 29, 2026 · nnasaki