candid-loop について
candid-loopは、問題がなくなるか上限回数に達するまでcandid-reviewと修正を繰り返すスキルです。開発者は自動、修正ごとの確認、対話型の処理を選び、カテゴリや除外ルールも設定できます。
主な機能
- 01candid-reviewの反復実行
- 02修正の自動適用または個別確認
- 03問題のスキップと除外
- 04カテゴリによる問題の絞り込み
- 05回数上限とレビュー規則の設定
活用シーン
- 01コードレビューで見つかった問題の修正
- 02影響の大きい修正を個別に承認
- 03既知の誤検出やカテゴリの除外
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ron-myers/ candid --skill candid-loopインストール後、Claude Code で/candid-loopを入力して読み込まれたか確認します。
詳細
Candid Loop
コードに問題がなくなるまで、candid-review を繰り返し実行します。このスキルは修正・レビュー・修正のサイクルを自動化し、問題がなくなるまで(または最大反復回数に達するまで)修正を適用してレビューを再実行します。
ワークフロー
次の手順を順番に実行します。
Step 1: 設定を読み込む
CLI フラグと設定ファイルからループの設定を読み込みます。
優先順位(高い順):
- CLI フラグ
- プロジェクト設定(
.candid/config.json→loopフィールド) - ユーザー設定(
~/.candid/config.json→loopフィールド) - デフォルト値
CLI 引数を確認する
CLI 引数を解析して、ループオプションを確認します。
| フラグ | 説明 | デフォルト値 |
|---|---|---|
--mode <auto|review-each|interactive> | 実行モード | auto |
--max-iterations <N> | ループの最大反復回数 | 5 |
--categories <list> | 適用するカテゴリ(カンマ区切り) | all |
有効なモード:
auto- すべての修正を自動的に適用しますreview-each- 修正を1つずつ確認します(それぞれについて Yes/No を選択)interactive- スキップ、無視、バッチ処理を含め、すべてを制御できます
有効なカテゴリ: critical、major、standards、smell、edge_case、architectural、all
CLI フラグが指定されている場合はその値を使用し、該当するオプションについては設定ファイルの確認をスキップします。
設定ファイルを確認してデフォルト値を適用する
.candid/config.json から loop フィールドを読み込みます(jq -r '.loop // null' .candid/config.json 2>/dev/null)。存在しない場合は、~/.candid/config.json を試します。CLI で設定されていない mode、maxIterations、enforceCategories にはそれぞれ設定ファイルの値を使用します。また、ignored {categories, patterns, ids} も抽出します。適用時には Using loop settings from project config または Using loop settings from user config と出力します。
それでも未設定の項目には、デフォルト値を適用します:mode = "auto"、maxIterations = 5、enforceCategories = ["all"]、ignored = { categories: [], patterns: [], ids: [] }。
- 既知の誤検出に該当するパターンを無視リストに追加します。
- maxIterations は 5~10 に保ちます。
Step 2: ループ状態を初期化する
追跡用の変数を設定します。
iteration = 0
totalFixesApplied = 0
allFixedIssues = []
registerQuestionsRaised = 0
registerQuestionsResolved = 0
registerPriorDecisionsApplied = 0
モードのバナーを表示します:[<Mode> Mode] Running candid-loop with max [N] iterations...。続けて、review-each の場合は2行目に「You will review each fix one by one.」、interactive の場合は「Full control: skip, ignore, or batch process fixes.」と表示します。
Step 3: レビューループを実行する
メインループを実行します。
WHILE iteration < maxIterations:
iteration++
Execute Step 3.1 through Step 3.6
IF exitLoop == true:
BREAK
IF iteration >= maxIterations AND remainingIssues > 0:
Output warning: "Max iterations ([N]) reached. [M] issues remain."
List remaining issues
ループの不変条件 — 違反しないこと
- PASS には最新のクリーンレビューが必要です。 最終反復で最後の修正を適用した後に candid-review を実行し、フィルタリング後の問題が0件だった場合に限り、ステータスを PASS にします。
.candid/last-review.jsonのタイムスタンプが最後の Edit より後であることを確認してください。以前の反復の結果から PASS と判断してはいけません。 - 進展がなければ停止します。 反復で適用した修正が0件で、フィルタリング後も問題が残っている場合は、直ちに INCOMPLETE で終了します。同一のレビューを繰り返しても解決には至りません。
- 振動を確認します。
allFixedIssuesにすでに含まれている問題 ID が後続の反復で再出現した場合は、停止します:Oscillation detected: fix for [id] was undone or reintroduced.手動で解決できるよう、両方の修正を一覧表示します。 - 却下済みの問題を再度尋ねないでください。 「No」または「Skip」でスキップされた ID を
sessionSkippedに追加し、後続の反復では Step 3.4 でフィルタリングします。これらは再確認の対象ではなく、INCOMPLETE の判定に含めます。
ステップ 3.1:candid-review を実行する
反復のヘッダーを表示します:
[Iteration [N]/[MAX]]
Running candid-review...
candid-review スキルを呼び出して、現在のコードを分析します:
- Skill ツールを使用して
/candid-reviewを実行します - 設定されている場合は、トーンの設定を引き継ぎます
- レビューが完了するまで待ち、状態を
.candid/last-review.jsonに保存します
注: candid-review は独自の修正選択プロンプトを表示します。自動モードでは、「すべての修正を適用」を選択して対応する必要があります。対話モードでは、candid-review 内でのユーザーの選択に従います。
決定レジスター: 設定で決定レジスターが有効になっている場合、candid-review の各反復はレジスターファイルを個別に読み取り、更新します。つまり、次のようになります:
- 反復 1 で提起された質問はレジスターに記録されます
- 反復 2 以降では、candid-review は同じ質問を再度提起する前にレジスターを確認します
- 以前の反復で質問に回答済みの場合、その回答が自動的に再利用されます
- 自動モードでは、レジスターに以前の回答がある「確認が必要」な問題は、プロンプトを表示せずに適用されます
ステップ 3.2:レビュー結果を読み取る
candid-review の完了後、保存されたレビュー状態を読み取ります:
cat .candid/last-review.json 2>/dev/null
JSON を解析し、次の項目を抽出します:
- 見つかったすべての問題を含む
issues配列 - 各問題には、
id、file、line、category、title、descriptionがあります
ファイルが存在しないか空の場合:
No review state found. candid-review may not have completed.
エラーで終了します。
ステップ 3.3:カテゴリで問題を絞り込む
enforceCategories が ["all"] でない場合:
enforceCategories に一致する問題だけが含まれるように、issues 配列を絞り込みます:
filteredIssues = issues.filter(issue =>
enforceCategories.includes(issue.category)
)
出力:Enforcing categories: [list]. Filtered to [N] issues.
ステップ 3.4:無視対象の問題を除外する
設定の無視フィルターを適用します。ignored.categories に含まれるカテゴリの問題、ignored.patterns のいずれかの正規表現にタイトルが一致する問題(大文字と小文字を区別しません)、または ID が ignored.ids に含まれる問題を削除します。
問題がフィルターで除外された場合:
Filtered out [N] ignored issues ([M] remaining)
ステップ 3.5:完了を確認する
filteredIssues.length === 0 の場合:
[Iteration [N]/[MAX]] No issues found!
exitLoop = true
ステップ 4(要約)に進みます。
ステップ 3.6:モードに応じて問題に対処する
mode == "auto" の場合:
見つかった問題を表示します:
[N/MAX] Found [M] issues. Applying fixes...
ユーザーがプロンプトで「すべての修正を適用」を選択していた場合、candid-review スキルはすでに修正を適用しています。auto モードでは、candid-review が自動適用するように設定されているはずです。
修正された問題ごとに、次のように記録します:
✓ [icon] Fixed: [title] in [file]:[line]
修正を追跡します:
totalFixesApplied += appliedCount
allFixedIssues.push(...appliedIssues)
auto モードでの決定レジスター:
決定レジスターが有効な場合、candid-review はステップ 6 でレジスターの参照を処理します(「確認が必要」な質問を提示する前)。auto モードでは:
- レジスターにある過去の決定は candid-review によって自動的に適用されます — 次のように記録します:
Applied prior decision (#N) for [file] - 新しい「確認が必要」な問題(過去の回答がないもの)は自動適用されず、人による入力が必要なため、レジスターでは
openとして記録されます - これらはループ内で「スキップ」として扱われます — ループ完了を妨げる未解決の問題には数えません
- 出力:
Applied [N] prior decisions, skipped [M] new questions requiring clarification
レジスターのアクティビティを追跡します:
registerPriorDecisionsApplied += priorDecisionsCount
registerQuestionsRaised += newQuestionsCount
registerQuestionsResolved += resolvedCount
resolvedCount は candid-review のステップ 10.5 の出力から取得します。これには、フェーズ 8b でユーザーが回答した質問と、再レビューで自動解決された質問が含まれます。各イテレーション後にレジスターファイルを読み、前回の読み込み時と比べて新たに解決されたエントリー数を数えます。
次のイテレーションに進みます。
mode == "review-each" の場合:
「はい/いいえ」の簡単なプロンプトを使い、修正を 1 つずつ確認します。
見つかった問題を表示します:
[N/MAX] Found [M] issues. Reviewing each...
各問題について、AskUserQuestion を使用します:
[1/M] [icon] [title]
File: [file]:[line]
Problem: [description]
質問:「この修正を適用しますか?」
選択肢:
- 「はい、この修正を適用する」
- 「いいえ、この修正をスキップする」
- 「差分を表示」 — 現在のファイル内容を基準に、修正を変更前/変更後の統一差分として提示し、その後「はい/いいえ」の選択肢のみで再度質問します
ユーザーの選択を追跡します:
- 「はい」の場合 → 修正を適用し、totalFixesApplied を増やします
- 「いいえ」の場合 → 次の問題に進みます
すべての問題の処理後、修正が 1 つでも適用されていれば、次のイテレーションに進みます。
mode == "interactive" の場合:
スキップ、無視、まとめて処理するための追加オプションを備えた、完全な制御モードです。
見つかった問題を表示します:
Found [M] issues:
各問題について、AskUserQuestion を使用します:
[1/M] [icon] [title]
File: [file]:[line]
Problem: [description]
質問:「この問題をどのように処理しますか?」
選択肢:
- 「修正を適用」— この修正を適用して続行します
- 「スキップ」— この問題をスキップして次に進みます
- 「無視リストに追加」— この問題 ID を ignored.ids に追加してスキップします
- 「残りをすべてスキップ」— 残りの問題を一覧表示してループを終了します
ユーザーの選択を追跡します:
- 「修正を適用」の場合 → 修正を適用し、totalFixesApplied を増やします
- 「スキップ」の場合 → 次の問題に進みます
- 「無視リストに追加」の場合 → 設定の ignored.ids に issue.id を追加して続行します
- 「残りをすべてスキップ」の場合 → exitLoop = true に設定し、内側のループを終了します
interactive モードですべての問題を処理した後、修正が 1 つでも適用されていれば、次のイテレーションに進みます。
ステップ 3.7:無視リストを更新する(要求された場合)
ユーザーがいずれかの問題について「無視リストに追加」を選択した場合:
- 現在の
.candid/config.jsonを読み込みます(存在しない場合は作成します) - 問題 ID を
loop.ignored.ids配列に追加します - 更新した設定をファイルに書き込みます
# Read, modify, write
jq '.loop.ignored.ids += ["issue-id-1", "issue-id-2"]' .candid/config.json > tmp.json
mv tmp.json .candid/config.json
出力:Added [N] issues to ignore list in .candid/config.json
ステップ 4:概要を表示する
ループの終了後(成功または最大イテレーション数到達)、最終概要を表示します:
Candid Loop [Complete|Stopped|Cancelled]
Summary:
- Iterations: [N]
- Issues fixed: [M]
- Status: [PASS|INCOMPLETE|CANCELLED]
INCOMPLETE の場合:Issues remaining: [P] を追加し、残りの問題を [icon] [title] in [file]:[line] の形式で一覧表示します。さらに、--max-iterations を増やす、誤検知を無視する設定を永続的に追加する、複雑な問題を手動で確認する、といったヒントを追加します。
CANCELLED の場合:Issues skipped: [P] を追加し、スキップした問題を一覧表示します。
決定レジスターのセクション(レジスターが有効な場合はすべての概要に追加):
設定で decisionRegister.enabled == true の場合、表示する概要の末尾に次のセクションを追加します:
Decision Register:
- Prior decisions applied: [N]
- New questions raised: [M]
- Questions resolved: [P]
- Open questions: [Q]
未解決の質問が残っている場合:
Open questions can be reviewed at: [registerPath]/review-decision-register.md
設定
設定ファイルのスキーマ
.candid/config.json に追加します:
{
"version": 1,
"tone": "harsh",
"loop": {
"mode": "auto",
"maxIterations": 5,
"enforceCategories": ["all"],
"ignored": {
"categories": [],
"patterns": [],
"ids": []
}
}
}
フィールドの説明
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
loop.mode | string | "auto" | "auto"、"review-each"、または "interactive" |
loop.maxIterations | number | 5 | レビューと修正のサイクルの最大数 |
loop.enforceCategories | array | ["all"] | 適用するカテゴリ |
loop.ignored.categories | array | [] | 完全にスキップするカテゴリ |
loop.ignored.patterns | array | [] | 問題タイトルに一致する正規表現パターン(例:["Unicode", "timezone"]) |
loop.ignored.ids | array | [] | スキップする特定の問題 ID |
CLI の例
# Run with defaults (auto mode, all categories, max 5 iterations)
/candid-loop
# Combine flags
/candid-loop --mode review-each --max-iterations 10 --categories critical,major
問題カテゴリのリファレンス
| カテゴリ | アイコン | 説明 |
|---|---|---|
critical | 🔥 | 本番環境に重大な影響を与える問題:クラッシュ、セキュリティ上の欠陥、データ損失 |
major | ⚠️ | 深刻な問題:パフォーマンス、エラーハンドリングの欠如 |
standards | 📜 | Technical.md の規約違反 |
smell | 📋 | 保守性に関する問題:複雑さ、重複 |
edge_case | 🤔 | 未処理のシナリオ:null、空、並行処理 |
architectural | 💭 | 設計上の懸念:結合度、SRP 違反 |