概要
/ndf:cross-review の修正フェーズで、fix サブエージェントが書き出す戻り値ファイル
$TMP_DIR/fix-pr<PR>-result.json の resolved_threads を int(件数) で書くと、
scripts/state.py merge-fix が len() を int に適用して TypeError でクラッシュし、
ループが止まります。頻繁に再発します。
- plugin:
ndf v4.12.1 - 該当:
skills/cross-review/scripts/state.pycmd_merge_fix(v4.12.1 では L704)
再現時のエラー
Traceback (most recent call last):
File ".../skills/cross-review/scripts/state.py", line 895, in <module>
main()
File ".../skills/cross-review/scripts/state.py", line 891, in main
args.func(args)
File ".../skills/cross-review/scripts/state.py", line 704, in cmd_merge_fix
"resolved_threads": len(fix.get("resolved_threads", []) or []),
~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'int' has no len()
fix-pr<PR>-result.json が例えば "resolved_threads": 3 のとき発生。
根本原因(ドキュメントの自己矛盾)
resolved_threads の表現がドキュメント間で食い違っており、エージェントが int を書きやすい:
| 箇所 | 表現 | 実態 |
|---|
docs/02-fix-and-rotation.md 戻り値スキーマ (L133付近) | list([{"thread_id":...,"path":...}]) | コードが期待する形 |
docs/01-state-and-review.md state.json 例 (L55) | "resolved_threads": 4(int) | state.json 側の保存形(len() 後) |
docs/01-state-and-review.md 説明 (L75) | 「resolveReviewThread で resolve した件数」 | int を連想させる |
state.py は fix結果=list を受け取り len() して state.json には int(件数) を保存する設計
だが、ドキュメントの「件数」表現により fix エージェントが fix結果側にも int を書いてしまう。
提案する改修(2点:両側で堅牢化)
1. fix結果JSONを list で返すよう強制(プロンプト/ドキュメント)
docs/02 の戻り値スキーマで resolved_threads が 必ず list であることを明記し、
「件数(int)ではない」と注意書きを追加。docs/01 L75 の「件数」という説明を、fix結果側は list・state.json 側は
その len()(int) である、と区別して記述。- fix サブエージェント起動プロンプト(
docs/02 Step 5 / 本体 skill の Step 5 説明、
および最終スイープ Step 7.5)でも list 形式を明示。
2. state.py 側を int でも list でも受理できるようにする(後方互換)
cmd_merge_fix の該当行を、int / list / None いずれも受理する正規化に変更:
def_count(v):
\"\"\"int(件数) でも list でも None でも件数(int)に正規化する。\"\"\"ifisinstance(v, int):
returnvifisinstance(v, (list, tuple)):
returnlen(v)
return0# ..."resolved_threads": _count(fix.get("resolved_threads")),
"deferred": _count(fix.get("deferred")),
"rejected": _count(fix.get("rejected")),deferred / rejected も同種の len() 適用箇所であり、同じく int 混入で落ちうるため
まとめて _count() 経由にすると再発防止になる(deferred は別途 for d in fix["deferred"]
で list 走査する箇所があるため、そちらは isinstance(..., list) ガードを追加)。
期待される効果
- fix エージェントが int / list どちらを書いてもループが止まらない。
- ドキュメントの一貫性が取れ、そもそも int を書きにくくなる。
補足
回避策として、発生時に fix-pr<PR>-result.json の resolved_threads を
["t1","t2","t3"] のような list に手で書き換えて merge-fix を再実行すると復旧できる
(今回はこれで継続できた)。
概要
/ndf:cross-reviewの修正フェーズで、fix サブエージェントが書き出す戻り値ファイル$TMP_DIR/fix-pr<PR>-result.jsonのresolved_threadsを int(件数) で書くと、scripts/state.py merge-fixがlen()を int に適用してTypeErrorでクラッシュし、ループが止まります。頻繁に再発します。
ndfv4.12.1skills/cross-review/scripts/state.pycmd_merge_fix(v4.12.1 では L704)再現時のエラー
fix-pr<PR>-result.jsonが例えば"resolved_threads": 3のとき発生。根本原因(ドキュメントの自己矛盾)
resolved_threadsの表現がドキュメント間で食い違っており、エージェントが int を書きやすい:docs/02-fix-and-rotation.md戻り値スキーマ (L133付近)[{"thread_id":...,"path":...}])docs/01-state-and-review.mdstate.json 例 (L55)"resolved_threads": 4(int)state.json側の保存形(len()後)docs/01-state-and-review.md説明 (L75)state.pyは fix結果=list を受け取りlen()して state.json には int(件数) を保存する設計だが、ドキュメントの「件数」表現により fix エージェントが fix結果側にも int を書いてしまう。
提案する改修(2点:両側で堅牢化)
1. fix結果JSONを list で返すよう強制(プロンプト/ドキュメント)
docs/02の戻り値スキーマでresolved_threadsが 必ず list であることを明記し、「件数(int)ではない」と注意書きを追加。
docs/01L75 の「件数」という説明を、fix結果側は list・state.json 側はその
len()(int) である、と区別して記述。docs/02Step 5 / 本体 skill の Step 5 説明、および最終スイープ Step 7.5)でも list 形式を明示。
2. state.py 側を int でも list でも受理できるようにする(後方互換)
cmd_merge_fixの該当行を、int / list / None いずれも受理する正規化に変更:deferred/rejectedも同種のlen()適用箇所であり、同じく int 混入で落ちうるためまとめて
_count()経由にすると再発防止になる(deferredは別途for d in fix["deferred"]で list 走査する箇所があるため、そちらは
isinstance(..., list)ガードを追加)。期待される効果
補足
回避策として、発生時に
fix-pr<PR>-result.jsonのresolved_threadsを["t1","t2","t3"]のような list に手で書き換えてmerge-fixを再実行すると復旧できる(今回はこれで継続できた)。