# 自己修復: 何をするか

> Latchkey ランナーが実行中に一時的な CI 障害をどのように検出し修正するか、決して触れないもの、そして修復の提案がどのようにレビュー可能なプルリクエストになるか。

Source: https://latchkey.dev/ja/documentation/self-healing

## Summary

- すべてのランナーが一時的な障害 (ネットワーク、構成、ツールの欠如、メモリ、ディスク) を **実行中に** 検出し修正します。デフォルトでオンです。
- 3 段階の診断: 終了コード、次にパターンライブラリ、次に制限付き AI。修正はエフェメラルなランナーにのみ触れます。
- 恒久的な修正は、あなたがレビューする **修復 PR** として届きます。実際のコード障害は元のログを保ったまま失敗します。
- あなた自身のコードの障害は、MCP 経由で構造化されたバンドルとして届きます: 根本原因、失敗した正確なファイル、完全なログ、あなたのコーディングエージェント向けに準備済み。

すべての Latchkey ランナーには自己修復が組み込まれており、デフォルトで有効です。ワークフローのステップが失敗すると、ランナーはその障害をローカルで診断し、既知の一時的なクラスであれば修正してそのステップをその場で再試行します。人間による再実行なしにビルドがグリーンになり、すべての介入があなたが検査できるよう記録されます。

## 3 段階の診断カスケード

診断は最速優先で実行されるため、よくあるケースはほとんどコストがかかりません:

1. **終了コードの照合 (即時)** いくつかの障害は自ら正体を明かします。メモリを使い果たしたプロセスをカーネルが kill した終了コード **137** は、この段階でただちに判定され修正されます。終了コード **127** (コマンドが見つからない) もここでフラグが立てられますが、実際の修正は第 2 段階のパターンライブラリとインストール許可リストから行われます。
2. **パターンライブラリ (決定論的)** ステップの出力は、既知の障害シグネチャの厳選されたライブラリと照合されます: npm、yarn、pnpm、pip、uv、Go モジュール、cargo、NuGet、Docker と GitHub のレジストリ、Composer、Bundler、Maven、apt、git にわたるレジストリのタイムアウトと 5xx 応答。DNS と TLS の不調。レート制限。ヒープの枯渇。ディスク満杯のエラー。ロックファイルのドリフト。パターンの一致は決定論的です: 同じ障害には毎回同じ修正です。
3. **制限付き AI 診断 (新規の障害)** 最初の 2 段階が認識しないものは、厳格な時間予算 (約 4 分) を持つサンドボックス化された AI エージェントに渡されます。キャプチャされた出力を読み、根本原因を推論し、ランナー内で安全な修正を適用するか、恒久的な修正をプルリクエストとして提案するか、あるいは障害が本物だと結論づけてそのままにします。

## 何をカテゴリ別に捕捉するか

> **意図的に捕捉しないもの**
> あなたのコードやテストの本物のバグ。ユーザーコードの障害はまさにそのように分類され、元のログを保ったまま通常どおり失敗します。自己修復はインフラのノイズを取り除くために存在するのであって、本物の障害を隠すためではありません。

## 修正ツールボックス

すべての修正はエフェメラルなランナー内でのみ適用され、ランナーはジョブの後に破棄されます:

- **バックオフ付き再試行** 一時的なネットワーク障害向け: 待ってからステップを再実行し、遅延を段階的に増やします。
- **環境を設定** 再試行のためにメモリ上限を引き上げます: NODE_OPTIONS、_JAVA_OPTIONS、GRADLE_OPTS など。
- **ディスクを解放** ジョブの途中でディスクが満杯になったとき、Docker レイヤー、パッケージキャッシュ、/tmp を削除します。
- **パッケージをインストール** 欠けているツールを apt-get install します。許可リストに制限されます: GitHub ホステッドランナーイメージにある同じパッケージセット。
- **コマンドの書き換え** 既知の不正な呼び出しを文書化された対処法に置き換えます (ロックファイルのドリフトで npm ci を npm install に)。

## 1 つの修復、エンドツーエンドで

これは、npm レジストリのタイムアウトという 1 つの実際の修復を、失敗したステップからグリーンなジョブまで追ったものです。あなたのステップ出力は変更されずリアルタイムでストリーミングされます。修復中は、ランナー上の修復サービスに問い合わせている間、ランナーが自身の診断行を 2 行だけ追加します:

```job log
$ npm ci
npm ERR! code ETIMEDOUT
npm ERR! syscall connect
npm ERR! network request to https://registry.npmjs.org/lodash failed, reason: connect ETIMEDOUT 104.16.92.83:443
npm ERR! network This is a problem related to network connectivity.
[latchkey-bash-wrapper] BEGIN sidecar POST (boot_wait=30s max_time=260s url=http://localhost/diagnose socket=/run/latchkey-self-heal/sock)
[latchkey-bash-wrapper] END sidecar POST ok (attempts=1 http=200)
$ npm ci
added 1291 packages, and audited 1292 packages in 42s
found 0 vulnerabilities
```

1. **ステップが失敗します。** npm が自身の内部再試行を使い果たした後、`npm ci` は非ゼロで終了します。ランナーはストリーミングされるステップ出力をキャプチャしていたため、診断は全体像を手にした状態で始まります。
2. **第 1 段階、終了コード。** 終了コード 1 はそれ単体では決定的ではないため、カスケードは次へ進みます。
3. **第 2 段階、パターン一致。** `ETIMEDOUT` の行が、パターンライブラリ内の既知の npm ネットワークシグネチャに一致します: 判定は **heal**、カテゴリは **network**、AI は関与しません。2 行の `[latchkey-bash-wrapper]` 行が、あなたのログにおけるこの問い合わせの唯一の痕跡です。
4. **バックオフ付き再試行。** この修復の計画では、2 秒から始まる段階的な遅延を伴う最大 3 回の試行が許可されています。ランナーは待機してから、同じマシン、同じワークスペースでステップを再実行します: ログ内の 2 回目の `npm ci` がその再試行です。
5. **グリーン。** 再試行が成功し、ジョブはタイムアウトなど起きなかったかのように続行します。成功時にあなたのログへそれ以上追加されるものはありません。マシンを変更する修復はそれを告知する (たとえば `[latchkey-bash-wrapper] installed package: ffmpeg`) ため、見えない介入はありません。

ログでは見えなかった経緯はダッシュボードにあります: [Runners ページ](/documentation/runners-dashboard) の **Recent Heals** フィードには、**Pattern match** のピルと取られたアクション ("Retried the npm command with exponential backoff after a network timeout") を伴う network カテゴリの **Healed** 行が表示され、**Heal Details** ドロワーが段階ごとの経緯を伝え、その実行は [パイプラインパフォーマンス](/documentation/pipeline-performance) でグリーンの **Healed** バッジを保ちます。

## 修復プルリクエスト

一部の根本原因は、実行中の救済だけでなく、あなたのリポジトリでの恒久的な修正に値します: ワークフローに欠けているセットアップステップ、`package.json` に欠けている `engines` の固定、低すぎるジョブのタイムアウト。成功した修復がこうした構造的な原因にさかのぼると、自己修復は構造化された提案を生成し、型付きで決定論的な編集を伴う **修復 PR** を開きます。

- 各 PR のタイトルは "Latchkey heal: <error summary>" です。本文は **Error**、**Root cause**、**Fix** を説明し、ワークフロー実行にリンクバックするため、レビューは数分で済みます。
- 提案 PR には検証ノートが付きます: PR 自身のワークフロー実行が成功した場合は **Verified by run**、そうでない場合は **Proposed fix, not verified by a passing run** です。
- 再試行が失敗した実行を救済した場合、提案はそれを定量化します ("Latchkey auto-retried this workflow N times; M passed on the retry")。ワークフローの再試行の合格率が低い場合、自動再試行は一時停止します。
- 修復 PR が自動マージされることは決してなく、**フォークからのプルリクエストには決して触れません**。
- PR の作成は GitHub App の権限を使用します。修復 PR を一度もマージしなければ、あなたのリポジトリでは何も変わりません。

### Declined fixes: 提案を停止する

すべての提案クラスがすべてのリポジトリで歓迎されるわけではありません。AI Insight ページの自己修復提案の検出結果には **Stop proposing** アクションがあります (オーナーと管理者)。Latchkey はその後、**Settings、Self-Healing、Declined fixes** で取り消すまで、そのリポジトリのその障害クラスに対する PR の作成を恒久的に停止します。自己修復はそれらの障害に対して引き続き動作します。ワークフロー変更の提案だけを停止します。

## することと決してしないこと

## あなたのコーディングエージェントに引き継ぐ

自己修復は環境を修正するのであって、決してあなたのソースを修正しません。本当の問題があなた自身のコードのバグである場合、ビルドは正直に失敗し、その障害は Latchkey MCP サーバー経由で提供される完全で構造化されたバンドルとして届き、あなた自身のコーディングエージェントがそこから修正できる状態になります。このバンドルは、エージェントが本来なら手作業で再構築するものを渡します:

- 平易な言葉での **根本原因**。
- 失敗したステップの **終了コード** と、エラーが表面化した **正確なソースファイル**。
- 失敗したステップの **完全で切り詰められていないログ**。GitHub がログビューアで隠す出力を含み、Latchkey を離れる前にシークレットが除去されています。
- 自己修復が **既に調査した** 内容となぜ手を引いたか、加えてワークフローの定義。

Claude Code では、組み込みの `/mcp__latchkey__fix` コマンドが往復を 1 ステップで行います: 直近の未修正の障害を取得し、作業に取りかかります。MCP 対応のあらゆるエージェント (Cursor、Codex など) は、サーバーのツールを通じて同じバンドルを読めます。セットアップ、API キー、そして用意済みの接続コマンドは [AI エージェントを接続する](/documentation/connect-your-ai-agent) にあります。

## オブザーバビリティ: すべての修復が記録される

- **Recent Heals** ([Runners ページ](/documentation/runners-dashboard) 上) は、すべての介入をそのカテゴリ、判定、そして取られたアクションの平易な言葉での説明とともに一覧します。AI が診断した修復にはエージェントの推論イテレーションが含まれます。
- **修復された実行はフラグが立てられ**、パイプラインパフォーマンスの実行テーブルでその修復レポートへディープリンクします。
- Runners ページの **修復の KPI と傾向** は、修復が実行を救う頻度とどのカテゴリが優勢かを示し、それ自体があなたのインフラに関するシグナルです。

| シグナル | 何を伝えるか |
| --- | --- |
| 結果バッジ | **Healed** (修正が成功)、**No Action** (システムが意図的に行動しなかった。たとえばあなた自身のコードの障害で)、**Failed** (修正が試みられたがステップを回復できなかった)、または **Pending** (結果がまだ記録されていない)。 |
| 修正タイプのピル | 修復がどう決定されたか: **Auto-fix** (決定論的な終了コードルール)、**Pattern match** (既知の修正を伴う既知の障害シグネチャ)、または **Agent fix** (エージェントが調査した)。 |
| エージェントのトランスクリプト | エージェント修復のステップごとの記録: 計画、ターンごとの仮説と推論、各アクションとその結果、そして所要時間。 |

## コントロール

- **Settings、Self-Healing** の **ワークスペースレベルのスイッチ** (オーナーと管理者)。新しいワークスペースではデフォルトでオンです。変更は約 1 分以内に反映されます。
- リポジトリごとのトグルはありません。ワークスペースのスイッチがすべての監視対象リポジトリに適用されます。
- **Declined fixes** も **Settings、Self-Healing** の下にあり、停止した提案クラスを一覧し、それぞれを取り消すオプションを備えています。

## よくある質問

### 自己修復はビルドを遅くしますか?

いいえ。ステップが失敗したときにのみ作動します。成功するステップは追加のレイテンシーゼロで実行されます。修復された障害には診断と再試行のコストがかかりますが、これは人間が赤いビルドに気づいて再実行をクリックするよりほぼ常にはるかに安上がりです。

### 私のシークレットを見られますか?

診断は、ジョブが既に出力するステップ出力に対して、あなたのランナー上でローカルに実行されます。新たに露出されるものはありません: GitHub Actions によってマスクされたシークレットはマスクされたままで、ランナーはジョブの後に破棄されます。

### 永遠に再試行して請求額を膨らませることはありますか?

いいえ。再試行はステップごとに制限され、AI 段階には厳格な時間予算があり、ランナー自体に 4 時間の寿命上限があります。また自己修復に別途料金はありません: 修復中の追加ランタイムはランナーの標準的な 1 分あたりの料金で課金されます。

### 障害を修正できない場合はどうなりますか?

そのステップは他のどのランナーとも同じように、元のログを保ったまま失敗し、加えて Recent Heals で読める診断が付きます。修復不能は、エラーではなく一級の判定です。

> **あなた自身のビルドで見てみる**
> 不安定なワークフローを 1 つ `runs-on: latchkey-small` に移し、1 週間 Recent Heals フィードを見てみてください。ほとんどのチームは数日以内に最初の救済されたビルドを目にします。[最初のジョブを実行する](/documentation/run-your-first-job)。

修復が実世界のどんな障害をカバーするかを見るには、Learn の [自己修復パターンライブラリ](/learn/self-healing-ci) を閲覧してください - 各エントリは手動の修正と、ランナーが自動で行うことを並べて示します。現在あなたのビルドを失敗させているものについては、完全な [CI/CD エラーライブラリ](/learn) から始めてください。

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
