背景 / コンテキスト
/forge:start-implement で forge-msg feature を実装中、/forge:review code --auto(engine=codex)の AI レビュー実行中に発生した。convert_codex_findings.py(review_<種別>.md の Codex 自由記述 Markdown を findings_<種別>.json に構造化変換するスクリプト)の抽出品質に関する不具合を2件確認した。いずれも Issue #201(severity/title 順序違いによるサイレントな finding 0件化)とは異なる症状であり、findingの検出自体は成功するが、抽出されたフィールドの内容にノイズが混入する種類の不具合のため、別 Issue として起票する。
現象(実際の動作)
症状1: 隣接する空 severity セクションの内容が finding の body/target_snippet に混入する
Codex のレビュー出力は 🔴致命的問題 / 🟡品質問題 / 🟢改善提案 の3セクション構成で、該当なしのセクションは規約により (なし) と記述される(agents/reviewer.md finding 出力フォーマット規約)。convert_codex_findings.py がある1件の finding を抽出する際、後続の空セクションの (なし) という文字列が誤って対象 finding の body/target_snippet フィールド末尾に連結される。
観察例(findings_code.json 内の実際のフィールド値):
"...この場合メッセージは未読のまま残り、次回また検知される\n\n\n(なし)\n\n\n(なし)"
症状2: title フィールドに severity ラベルの断片が残存する
Codex が 1. **[critical] タイトル文言**: 説明... のように severity ラベルを **...** の内側先頭に埋め込んだ場合、convert_codex_findings.py の title 抽出処理が [ の除去に失敗し、critical] という断片が title 文字列の先頭に残る。
観察例:
{"title": "critical] notify.py の単体テストが存在しない", "severity": "critical", ...}
severity/priority/recommendation 等の判定用フィールド自体は正しく抽出されており、下流の evaluator 判定処理には実害がないが、title/body/target_snippet が人間向け表示(review_<種別>.md の正規化ビュー等)に使われる際にノイズとして残る。
期待動作
- 症状1: 対象 finding のセクション境界を正しく検出し、後続の空セクション文字列(
(なし)等)が finding のフィールドに混入しないこと
- 症状2: severity ラベル(
[critical] 等)が **...** の内側に埋め込まれていても、title 抽出時にラベル全体([ と ] を含む)を正しく除去すること
再現手順
いずれも Codex の出力の自由度に依存するため、100% 確実な再現手順ではない。
症状1:
/forge:review code --files <対象ファイル> --auto(engine=codex)を実行する
- Codex が finding の説明文の後に空行を複数含む形式で出力し、かつ後続に空の severity セクション(
(なし))が続く
convert_codex_findings.py --kind code 実行後、findings_code.json の該当 finding の body/target_snippet 末尾に (なし) が連結されていることを確認する
症状2:
- 同上の
/forge:review code --auto を実行する
- Codex が
1. **[severity] タイトル**: ... の形式(severity ラベルを **...** の内側先頭に埋め込む)で出力する
findings_code.json の該当 finding の title フィールド先頭に severity] という断片が残っていることを確認する
環境情報
- リポジトリ: BlueEventHorizon/bw-cc-plugins(
develop ブランチ、plugins/forge/scripts/review/convert_codex_findings.py)
- 実行環境: Claude Code、Codex CLI(
codex-cli 0.144.1 で確認)
重大度
軽微
証跡
なし
原因
convert_codex_findings.py(内部で findings_parser.py の抽出ロジックを使用)のセクション境界検出・フィールド抽出用の正規表現が、Codex の出力形式の揺れ(空セクションの直後に別 finding の内容が続く配置、severity ラベルが **...** の内側に埋め込まれる配置)を十分に吸収できていない。Issue #201(severity/title 順序違いによる finding 0件化)と根本原因(Codex 出力形式の揺れに対する抽出ロジックの脆弱性)は共通するが、症状・影響範囲が異なるため別 Issue として管理する。
実装計画
関連ドキュメント
仕様書
参考 PR(実装パターン)
実装スコープ
| レイヤー |
実装内容 |
ファイルパス |
| Codex 構造化変換(縮退経路、ADR-033 §6) |
症状1: extract_findings() のセクション境界検出で、#### P1/P2/P3 サブセクション見出し(h4以深)通過時も flush_body() を呼び、直前 finding の body/target_snippet を確定させる(severity 自体は継続、Issue #151 と非衝突) |
plugins/forge/scripts/review/findings_parser.py |
| 同上 |
症状2: FINDING_PATTERN に **[label] title** 形式(severity ラベルが太字内・タイトル前)専用の分岐を追加し、title 抽出時にラベル全体([/] 含む)を除去する。group 番号変更に伴う参照箇所(heading 側 if match: ブロック・body 側 if match: ブロックの計2箇所、_strip_leading_finding_marker)を追従修正 |
同上 |
スコープ外
| 項目 |
理由 |
担当 |
agents/reviewer.md / templates/review_result.md の出力フォーマット規約変更 |
PR #211 と同方針。プロンプト強化のみでの対症療法は行わない |
- |
convert_codex_findings.py の変更 |
findings_parser の関数を呼ぶのみで内部ロジック変更は波及しない |
- |
TODO
着手前確認
実装する
テストを書く
確認・レビュー準備を行う
完了する
背景 / コンテキスト
/forge:start-implementで forge-msg feature を実装中、/forge:review code --auto(engine=codex)の AI レビュー実行中に発生した。convert_codex_findings.py(review_<種別>.mdの Codex 自由記述 Markdown をfindings_<種別>.jsonに構造化変換するスクリプト)の抽出品質に関する不具合を2件確認した。いずれも Issue #201(severity/title 順序違いによるサイレントな finding 0件化)とは異なる症状であり、findingの検出自体は成功するが、抽出されたフィールドの内容にノイズが混入する種類の不具合のため、別 Issue として起票する。現象(実際の動作)
症状1: 隣接する空 severity セクションの内容が finding の body/target_snippet に混入する
Codex のレビュー出力は
🔴致命的問題/🟡品質問題/🟢改善提案の3セクション構成で、該当なしのセクションは規約により(なし)と記述される(agents/reviewer.mdfinding 出力フォーマット規約)。convert_codex_findings.pyがある1件の finding を抽出する際、後続の空セクションの(なし)という文字列が誤って対象 finding のbody/target_snippetフィールド末尾に連結される。観察例(
findings_code.json内の実際のフィールド値):症状2: title フィールドに severity ラベルの断片が残存する
Codex が
1. **[critical] タイトル文言**: 説明...のように severity ラベルを**...**の内側先頭に埋め込んだ場合、convert_codex_findings.pyの title 抽出処理が[の除去に失敗し、critical]という断片が title 文字列の先頭に残る。観察例:
{"title": "critical] notify.py の単体テストが存在しない", "severity": "critical", ...}severity/priority/recommendation等の判定用フィールド自体は正しく抽出されており、下流の evaluator 判定処理には実害がないが、title/body/target_snippetが人間向け表示(review_<種別>.mdの正規化ビュー等)に使われる際にノイズとして残る。期待動作
(なし)等)が finding のフィールドに混入しないこと[critical]等)が**...**の内側に埋め込まれていても、title 抽出時にラベル全体([と]を含む)を正しく除去すること再現手順
いずれも Codex の出力の自由度に依存するため、100% 確実な再現手順ではない。
症状1:
/forge:review code --files <対象ファイル> --auto(engine=codex)を実行する(なし))が続くconvert_codex_findings.py --kind code実行後、findings_code.jsonの該当 finding のbody/target_snippet末尾に(なし)が連結されていることを確認する症状2:
/forge:review code --autoを実行する1. **[severity] タイトル**: ...の形式(severity ラベルを**...**の内側先頭に埋め込む)で出力するfindings_code.jsonの該当 finding のtitleフィールド先頭にseverity]という断片が残っていることを確認する環境情報
developブランチ、plugins/forge/scripts/review/convert_codex_findings.py)codex-cli 0.144.1で確認)重大度
軽微
証跡
なし
原因
convert_codex_findings.py(内部でfindings_parser.pyの抽出ロジックを使用)のセクション境界検出・フィールド抽出用の正規表現が、Codex の出力形式の揺れ(空セクションの直後に別 finding の内容が続く配置、severity ラベルが**...**の内側に埋め込まれる配置)を十分に吸収できていない。Issue #201(severity/title 順序違いによる finding 0件化)と根本原因(Codex 出力形式の揺れに対する抽出ロジックの脆弱性)は共通するが、症状・影響範囲が異なるため別 Issue として管理する。実装計画
関連ドキュメント
仕様書
参考 PR(実装パターン)
実装スコープ
extract_findings()のセクション境界検出で、#### P1/P2/P3サブセクション見出し(h4以深)通過時もflush_body()を呼び、直前 finding の body/target_snippet を確定させる(severity 自体は継続、Issue #151 と非衝突)plugins/forge/scripts/review/findings_parser.pyFINDING_PATTERNに**[label] title**形式(severity ラベルが太字内・タイトル前)専用の分岐を追加し、title 抽出時にラベル全体([/]含む)を除去する。group 番号変更に伴う参照箇所(heading 側if match:ブロック・body 側if match:ブロックの計2箇所、_strip_leading_finding_marker)を追従修正スコープ外
agents/reviewer.md/templates/review_result.mdの出力フォーマット規約変更convert_codex_findings.pyの変更findings_parserの関数を呼ぶのみで内部ロジック変更は波及しないTODO
着手前確認
実装する
FINDING_PATTERNに severity ラベルのインライン分岐を追加し、**[label] title**形式の title からラベル断片が残らないよう修正extract_findings()の見出し処理で、h4 以深のサブセクション見出しもflush_body()を呼ぶよう修正(severity は継続)extract_findings内2箇所、_strip_leading_finding_marker)を追従修正テストを書く
findings_parser.extract_findings: 症状1(空サブセクションプレースホルダーの body 混入)の回帰テストfindings_parser.extract_findings: 症状2(**[label] title**形式の title 抽出)の回帰テスト確認・レビュー準備を行う
python3 -m unittest discover -s tests -p 'test_*.py'、全1463件パス)完了する