Imported from SH11235/rshogi (
AGENTS.md). Install upstream withnpx skills add SH11235/rshogi. Copyright stays with the author.
rshogi Agent Guide
0. スコープと言語
- ここは Rust で書かれた将棋エンジン rshogi のリポジトリです。
- このコードベースでは日本語でやり取りすること。ドキュメントやコメントも可能な限り日本語(英語併記可)でまとめてください。
Claude / Coding Expectations
早すぎる最適化は禁止
- 測定なしの最適化は禁止。ボトルネック議論では実測データか再現手順をセットで提示すること。
YAGNI(必要になるまで書かない)
- 将来用のフィールド/フラグ追加、未使用コードの温存は禁止。
追加ベストプラクティス
- パニックより
Resultを優先し、公開 API には///ドキュメントを付与。
必須チェック
cargo fmt && cargo clippy --fix --allow-dirty --testscargo testbash scripts/check-tracked-abs-paths.sh(tracked file に machine 依存の絶対パスを書かない。データは$SHOGI_DATA、外部 repo は/path/to/...を使う)
- Clippy の警告は
cargo clippy --fix --allow-dirty --tests→ 手動修正 → 再実行でゼロに。必要なら再度cargo fmt。 - 警告抑止のために安易に
#[allow(...)]や未使用変数へ_接頭辞を付けることは禁止。
共有データ($SHOGI_DATA)
教師データ / NNUE モデル / progress 係数 / 学習 checkpoint は repo 外の共有 root
(環境変数 $SHOGI_DATA)に置く。layout:
teachers/— 教師データ (PSV / packed bin)nnue/— engine 配備モデル(USIEvalFileで読む)progress/— progress 係数(LS_PROGRESS_COEFF)runs/bullet/,runs/tatara/— 各 trainer の学習 checkpoint
各自の共有データ root を SHOGI_DATA に export して使う。tracked file には machine
固有の絶対パスでなく $SHOGI_DATA を書く(外部 repo は /path/to/... placeholder)。
ツール開発(crates/tools)
大量データを扱うツールはスケーラブルに設計する
- 教師データの生成・抽出・処理系ツールは数千万〜億局面規模の入力を前提とする。
全件を
Vec等に load してから処理する設計(load-all)は禁止し、入力件数に対して ピークメモリが線形に増える実装を避ける。streaming / reservoir sampling 等で ピークメモリを入力件数に非依存にすること。 - これは「早すぎる最適化は禁止」と矛盾しない。入力が大量だと確定している領域の スケーラビリティは micro-optimization ではなく設計要件である。スケーラビリティ 改修時は before/after の実測(ピーク RSS・処理時間)を添える。
ツールの新規追加・改修時はユーザー doc を更新する
crates/toolsのバイナリを追加・改修したら、同じ PR でcrates/tools/docs/<tool>.mdと索引(crates/tools/docs/tools-reference.md/crates/tools/README.md)を更新する。- CLI フラグ・出力ファイル・セマンティクスを変えたら doc も必ず合わせる。
perf / メモリのレビュー指摘を「現スケールでは問題ない」で却下しない
- perf / メモリの指摘が出たら、現在のテスト規模ではなく想定する最大入力規模で 見積もってから採否を決める。本番入力が桁違いに大きいと、現スケールの感覚で 却下した指摘が本番でメモリ破綻になる。
サンプリング / 抽出ツールは決定性を担保する
- seed 固定 + 入力順固定(パス・ID のソート)で出力が bit 一致することを保証し、 同一 seed 2 回実行の一致をテストで検証する。HashMap 反復順などの非決定の混入に注意。
Unsafe コードポリシー
unsafeは原則禁止- 許可される場所: SIMD最適化、スタック割り当て、置換表など性能上必須な箇所、
および安全な代替 API が存在しない外部ライブラリ起因バグの回避(例: exit 時
デストラクタ連鎖の破損を避ける
_exit)のみ - 各
unsafeブロックには以下を必ずコメントで記載:- なぜ安全か
- 守るべき不変条件
長時間実行タスク
- 自己対局・ベンチマーク等の長時間コマンドは
run_in_background: trueでバックグラウンド実行すること - これにより Claude がプロセス監視・結果集計を自律的に行える
- 完了待ちには
TaskOutputツールを使用
YO alignment 調査の既知事実
乖離調査時に再調査不要な確認済み領域:
- TT 実装: エントリサイズ、クラスタ構造、probe/save/replacement policy、generation — 全て YO と完全一致確認済み
- NNUE 評価値: 同一局面で fresh NNUE eval は完全一致
- TT eval 信用問題:
use-lazy-evaluatefeature で eager/lazy 切り替え可能 (default: eager、eval_helpers.rsで常にnnue_evaluate()を呼ぶ)。lazy 有効時は TT hit && !PvNode でttData.evalを再利用し NPS +2.41% (2026-04-13 計測、v92+sfcache 基準、instructions/cycles 同方向で CPI 回帰なし)。ただし TT key16 衝突による偽 hit の eval が伝播し探索木が変わる (startpos は一致、複雑な中盤局面では nodes/pv divergent)。棋力検証 (selfplay) 未実施のため default は eager 維持 - pinned_pieces_excluding: avoid 駒を pinner 候補から除外するよう修正済み
- root correction_value: in_check に関わらず常に計算するよう修正済み(LMR の r 計算で使用されるため)
再発パターン:
mate_1plyの差異 → TT カスケード伝播 → 大規模ノード乖離。新しい乖離が見つかったらmate_1plyを最初に A/B テストまたは FEATURE_COUNT で確認すべき。- バッファ collect パターン: MovePicker の手を事前にバッファに全 collect してからイテレートすると、TT手の探索前にスコアリングが固定され、captureHistory 等の history 値が探索後と異なる。YO 準拠の逐次
next_move方式を使うこと。(ProbCut で発見・修正済み)
SE と stack 上書きの注意
YO のコード順序(reduction → ttPv調整 → lmrDepth → Step14 → SE → do_move)を忠実に守る。SE の再帰 search_node が同一 ply の stack を上書きするため、SE 前に参照すべき値(tt_pv 等)を SE 後に参照するとバグになる。
調査効率化の原則
- ログが出ない = 条件ミスではなくコードパスが異なる可能性を疑う。main moves loop で出ないなら ProbCut/NullMove 等の pre-loop パスを確認。
- PLY drill-down が深い(p>=4)場合は A/B テストを先に試す。疑わしい機能を両エンジンで無効化→乖離消失の確認は O(1) で原因経路を絞れる。
- 静的コード比較で見つからない乖離は「実行タイミングの差」を疑う。同一式でも history/TT の参照タイミングが異なるとスコアが変わる。
- r が全 root move で同一の定数オフセット → root レベル変数を疑う。correction_value, improving, delta 等の root 共通変数が原因。per-move 変数なら手ごとに値が異なるはず。
YO乖離調査の最短導線(2026-02-23 追記)
- 新しい乖離が出たら、まず
.claude/skills/yo-measure/SKILL.mdの「最短ルート(first mismatch固定)」に従うこと。 - 最初にやることは必ず以下の順:
depth一致帯を確定(どこまで一致するか)- 乖離が出る最初の
iter/mc/mvを root 粒度で1件確定 root+pm chain+ply+depth(+window)で同一文脈ゲートして1 plyずつ降りるvalではなくndの最初の差分点を固定- 必要時は
TT probe/writeをseq + fullkey + cluster/slotで時系列化
alpha/beta単独ゲート、全return箇所への無差別ログ追加は非推奨(混入とノイズで時間を失いやすい)。
詳細は docs/performance/yo_alignment_status.md と .claude/skills/yo-measure/SKILL.md を参照。
今回の実例は docs/performance/yo_alignment_case12013_findings_20260222.md を参照。
性能制約
- ホットパスでのヒープ割り当て禁止
- 評価ループ内での
Vec再割り当て禁止 - スタック割り当てと const generics を優先