PJR-KAQV agent失敗時の生のstderrを保全する
1. 概要
PJR-E6HG の調査では、失敗した実行の stderr ログに原因を示すメッセージが残っておらず、stdout の切り詰められた要約行だけが手がかりだった。そのため原因を推測に頼らざるを得ず、初回の結論が誤りとなった。agent が非ゼロ終了した場合に生の stdout と stderr を evidence の一部として保全し、失敗理由の要約とは別に参照できるようにする。認証情報などの秘密が混入しうる点を踏まえ、保全先と取り扱いもあわせて定める。
2. 完了条件
- reporter 段階が非ゼロ終了した場合に、その生の stdout と stderr が保全され、後から参照できる。現在は executor 段階のみ
recordExecutorEvidenceがlog_refsとして記録しており、reporter 段階の出力はどこにも残らない。 - 保全した出力から、失敗理由の要約では失われる情報を追える。PJR-E6HG では記録が
agent exited with non-zero code: "... is not valid JSONの切り詰められた1行のみで、原因を特定できなかった。この状態が解消している。 - 既存の秘密情報の秘匿(
redactSensitiveText)が保全した出力にも適用される。Bearer トークン、API キー、passwordなどの既存パターンを通す。 - 保全先とサイズ上限が定められている。既存の
MAX_LOG_BYTES(64 KiB)と同じ扱いにするか、別に定めるかを判断し、理由を記録する。切り詰めが発生した場合はその旨が分かる。 - 保全した出力が Git 管理下に入るか否かが明示されている。入る場合は秘密混入時の影響、入らない場合は worktree 削除時の消失を、それぞれ許容できる形で扱う。
- executor 段階についても、非ゼロ終了時に
log_refsの内容が原因調査に足りるかを確認し、不足があれば揃える。 - 保全の有無と内容を確認する自動テストが追加されている。
npm run typecheck、npm run lint:ts、npm run test:unit、npm run test:integrationが成功する。
3. 作業内容
| No | 作業 | 担当 | 状態 | メモ |
|---|---|---|---|---|
| 1 | reporter 段階の出力が保全されていない経路を特定する | ARC | done | Schedule / in-place / register / resume の reporter 経路を確認 |
| 2 | 保全先、サイズ上限、Git 管理下に置くか否かを判断し理由を記録する | ARC | done | run 単位の evidence 配下、stdout / stderr ごとに 64KiB、Git 管理対象とした |
| 3 | 保全を実装し、既存の秘匿処理を適用する | ARC | done | recordReporterFailureOutput で redactSensitiveText を適用 |
| 4 | 保全の有無と内容を確認するテストを追加する | ARC | done | 非ゼロ終了、形式再試行、秘匿、ストリーム分離、切り詰め、evidence 参照を自動テスト化 |
4. 対応結果
- reporter が非ゼロ終了または形式エラーで失敗した場合、各形式試行の stdout と stderr を
exec/evidence/<task>/<run>/reporter-attempt-<n>.<stdout|stderr>.logへ分離して保存し、evidence.jsonのlog_refsから参照できるようにした。失敗理由の要約とは別に、上限内で出力順を保ったストリーム内容を確認できる。 - 保存前に既存の
redactSensitiveTextを適用し、Bearer トークン、sk-/gh*_形式のキー、api_key/token/passwordなどを伏せ字化する。各ストリームは既存のMAX_LOG_BYTESと同じ 64KiB 上限とし、bytesとtruncatedを参照情報へ記録する。stdout / stderr を別枠にしたのは、一方の大量出力で原因を含む他方が失われることを避けるためである。 - Schedule の worktree / in-place、register の通常実行 / worktree / reporter resume の全 reporter 経路を同じ保存処理へ接続した。同じ run の resume が再度失敗した場合は直近の失敗ログで置換し、
log_refsの最大件数内に保つ。 - evidence 配下は Git 管理対象とした。成功して統合された run のログは履歴に残る一方、失敗中の worktree では未コミットであり、worktree を破棄すると消失する。既知の秘密パターンは保存前に秘匿するが、未知形式の秘密が残る可能性があるため、外部共有前の確認を運用上の前提とした。
- executor は従来から stdout と stderr の秘匿済み内容を
executor.logに最大 64KiB で保全し、log_refsに切り詰め有無を記録しているため、今回の不足は reporter 側に限定されると判断した。reporter は原因調査でストリーム境界が重要なため別ファイルとした。 - 対象単体テスト 11 件で、非ゼロ終了時の stdout / stderr 収集、形式エラー時の全試行収集、秘匿、64KiB 切り詰め、
evidence.jsonからの参照を確認した。全 unit suite は sandbox 内で既存のgit check-ignore -z --stdin子プロセスが終了せず完走できなかったため、停止しない環境での全件再検証が必要である。
5. 関連ドキュメント
- 保全が必要になった調査: PJR-E6HG claude-reporterがJSON解析失敗で再現性をもってブロックする
- 同じ reporter 段階の課題: PJR-Q828 reporterが解消済みの検証失敗を再評価できない問題を解消する
- exec の運用: exec運用ガイド
- evidence とログの設計: exec設定ガイド