Chunk の Fix error ボタンが的外れな修正 PR を出す時、何が起きているのか

Chunk の Fix error ボタンが的外れな修正 PR を出す時、何が起きているのか
Article actions
View in Markdown

Requires Chrome (latest) built-in AI.

Requires Chrome (latest) built-in AI.

CircleCI の Chunk (Beta) には Fix error ボタンがあります。失敗したステップの横に出るこのボタンを押すと、Chunk が修正 PR を自動で作ってくれます。CIエラーの修正を任せれる便利機能なのですが、Beta版なためか、時々まったく見当違いの PR が返ってくることがあります。ハルシネーションによるものか、それともなにかトラブルがおきているのか。AI Slop的なPRを出してくる時、Chunk内部で何が起きていたのかを半ば強引に観察してみたので、まとめます。

*この記事に書いた内容は 2026 年 4 月時点の筆者の観察に基づくものです。Chunk は Beta のため、今後動作が変わる可能性があります。

起きたこと

demo-symfony という Symfony リポジトリで PHPStan の CI ジョブが失敗したので、Fix error ボタンを押しました。約 28 分待って返ってきた PR がこれです。

Root cause として「PHPStan requires the Symfony container XML file」と書かれており、cache:clear を追加するという修正案が入っていました。

ところが phpstan.dist.neon や実コードを見ると、本来の失敗原因は PHPStan のレベル 6 で検出される型注釈の不足 でした。cache:warmup や container XML とはまったく関係ありません。修正後のパイプラインも当然 PHPStan で失敗しました。

なぜこうなったのかを調べるため、失敗したジョブのステップ出力を開いてみました。

ステップ出力に残っているのは「Note: Using configuration file …」と「Exited with code exit status 1」だけです。エラー本文がどこにもありません。

Chunk は何を見ていたか

このジョブの .circleci/config.yml を見ると、原因がわかりました。

- run:
    name: PHPStan
    command: |
      mkdir -p phpstan-junit-results
      vendor/bin/phpstan analyse --no-progress \
        --error-format=junit > phpstan-junit-results/phpstan.xml
- store_test_results:
    path: phpstan-junit-results

PHPStan の出力を --error-format=junit で JUnit XML に変換し、そのままリダイレクトで phpstan.xml に書き込んでいます。これは CircleCI が推奨する store_test_results と組み合わせる標準的な書き方です。CircleCI の Test Insights タブを開くと、PHPStan が検出した警告がちゃんと表示されます。

buildPayload() の引数 $arguments に iterable 型の value type が指定されていない、という警告が 796 件。これが本来 Chunk に直してほしかったエラーです。

標準出力されていない結果をChunkは認識しない

ここで疑問が出てきます。Chunk はこの JUnit XML を読んでいたのでしょうか。

Chunk の公式ドキュメントを読み比べると、モードによって記述に差があります。Fix flaky tests モード については「Chunk continuously monitors test results stored in CircleCI」と明記されており、store_test_results のデータを参照することが書かれています。一方 Fix error ボタンについては「Chunk reads the failure details and starts working on a fix」とだけあり、具体的に何を読むかは書かれていません。

観察した挙動から見る限り、Fix error ボタンが参照しているのは失敗ステップのステップ出力テキストだけで、store_test_results の JUnit XML は入力に含まれていないように見えます。ドキュメントに明記されていないので断定はできませんが、今回 Chunk が真のエラーに一切触れていないことと整合します。

ステップ出力が実質 2 行しかない状態で「修正 PR を作れ」と言われた Chunk は、手元にある .circleci/config.ymlphpstan.dist.neon から推測するしかありません。結果として出てきたのが、冒頭の「container XML が足りない」という見当違いの仮説でした。

stdout にエラーを残して試す

Fix error ボタンに真のエラーを届けるため、YAML を書き換えてステップ出力に PHPStan の警告を残すようにしました。

- run:
    name: PHPStan
    command: |
      mkdir -p phpstan-junit-results
      vendor/bin/phpstan analyse --no-progress \
        --error-format=junit > phpstan-junit-results/phpstan.xml \
      || (vendor/bin/phpstan analyse --no-progress --error-format=table; exit 1)

1 回目は今まで通り JUnit XML を出力します。成功すればそのまま終わります。1 回目が失敗した場合だけ || 以降が動き、--error-format=table で PHPStan をもう一度走らせて、今度は人間可読な形でステップ出力(stdout)にエラーを流します。最後の exit 1 でジョブ失敗の扱いを確定させます。

この書き方だと PHPStan を 2 回走らせるので CI 時間は伸びますが、失敗時のみなので普段のコストはかかりません。

書き換えて push した後の失敗ジョブのステップ出力がこちらです。

今度は missingType.iterableValue という PHPStan のエラー識別子や、各警告の行番号・メソッド名まで stdout に残っています。5000 行を超えるログです。

この状態でもう一度 Fix error ボタンを押してみました。返ってきた PR がこれです。

Root cause に「PHPStan level 6 was reporting 796 missingType.iterableValue errors across the codebase」と書かれています。今度は Chunk が真のエラーを認識しました。ステップ出力にエラーを残す、という当たり前の変更で Fix error ボタンは動き始めました。

件数が多いと Chunk は別の判断をする

ただし、認識した後の Chunk の判断が期待通りかどうかは別の話でした。今回の Chunk の修正方針は、PHPDoc の型注釈を整備するのではなく、phpstan.dist.neonignoreErrorsmissingType.iterableValue を追加して 796 件全部を黙らせる という方向でした。PR 説明文にも「This suppresses all 796 errors that were blocking the CI pipeline」と率直に書かれています。

Chunk のログを追ってみると、この判断の裏で何が起きていたかが少し見えます。Chunk は最初、ステップ出力ファイル全体を読もうとして制限に引っかかっていました。

「File content (456KB) exceeds maximum allowed size (256KB)」と出ています。Chunk の実行環境内のツールには読み込み上限があるようで、今回のログは 456KB まで膨らんでいたので単純な Read では全体を取り込めていませんでした。

その後 Chunk は次のような動きをしていました。観察できた範囲で書きます。

  • ログを grep で部分的に読み、エラー識別子と影響ファイルを特定する
  • 個別のソースファイルを直接開き、PHPDoc を追加する修正を sed も使いながら広範囲に進めようとする
  • この方向の作業がターン数上限で途中打ち切りになる
  • 別セッションで同じエラーを再分析し、今度は「コードはすでに PHPDoc がついている。PHP のネイティブ型ヒントでは generic array 型を書けないので、ignoreErrors で抑制するのが妥当」という判断で phpstan.dist.neon を書き換える

最終的に PR に反映されたのは後者の結果だけです。ユーザーから見ると、Fix error ボタンを 1 回押して 1 つの PR が返ってきただけに見えますが、内部では複数の試行が走っていたようでした。

参考までに、別プロジェクトで少数のテスト失敗を Chunk に直してもらったときには、ちゃんと修正方向の PR が返ってきました。

サンプルが少ないので断定はできませんが、筆者が観察した限りでは、エラーの規模や量で Chunk の挙動が変わるように見えます。

  • 入力がほぼゼロのとき(今回の最初のケース)は、周辺ファイルから推測して見当違いの仮説を立てる
  • 入力が大量のとき(今回の 2 回目のケース)は、コード修正を試みつつ途中で方針を切り替え、最終的に設定での抑制を選ぶこともある
  • 入力が適度な量のときは、期待通りに動くケースが確認できる

Fix error モードには、修正方針を指定するカスタムインストラクション機能が現時点の公式ドキュメントには記載されていません。Fix flaky tests モードには .circleci/fix-flaky-test.md というファイルで方針を指定できる仕組みが 2025 年 10 月に追加されているので、Fix error モードにも同じ仕組みが入ると、抑制を禁止する・修正のみ許可するといった制御がユーザー側でできるようになりそうです。

今言えること

観察から言えるのは次の 3 点です。

1 つ目。ステップ出力にエラー本文が残らない CI 構成では、Fix error ボタンはまず働きません。JUnit XML 等にリダイレクトして store_test_results に渡す構成は CircleCI の推奨ですが、Fix error ボタンの入力には現時点では届いていないように見えます。ワークアラウンドとしては、失敗時だけ人間可読なフォーマットで再実行して stdout にもエラーを残す書き方が使えます。

2 つ目。ステップ出力にエラーを残しても、量が極端に多いときは Chunk のログ読み込みが部分的になり、挙動が読みにくくなります。今回の観察では 456KB のログに対して 256KB の読み込み上限が見えました。これは Chunk 内部の実装上の値なので今後変わる可能性があります。

3 つ目。Chunk が認識した後の修正方針の選び方は、現状ユーザー側から制御できません。静的解析の大量エラーのような「本来コード側を直すべき」問題に対して、Chunk が設定での抑制を選んでくる可能性があります。PR を自動マージに流すような運用だとリスクになるので、少なくとも静的解析系のジョブに対する Fix error PR はレビュー必須にしておくのが無難です。

Chunk は Beta なので、ここに書いた挙動は今後改善されていく可能性があります。気づいた点は CircleCI の Chunk チームにもフィードバックを送っています。仕様が確定したら追記します。

Share:

Hidetaka Okamoto profile photo

Hidetaka Okamoto

Developer Experience Engineer

Developer Experience Engineer. A developer specialized in serverless application development on AWS and Cloudflare. Former Stripe Developer Advocate / AWS Samurai 2017. Skilled in creating content and presentations that introduce service usage and best practices. You can follow me on Twitter at @hidetaka_dev