008 消える足あと：教材の新規検証

検証対象
01_grid.py / 02_delivery.py / 03_reveal.py / 04_signboard.py / 05_two_letters.py
最終段の原作範囲：地図C・配置0・stations。
01〜04は小さな教材用10マス。原作A/Bの完全再現ではありません。

新規テスト
・qa/model_tests.txt：56テストすべて成功。任意の直接原作比較も実行。
・qa/standalone_tests.txt：原作なしの配布物コピーで56テストを実行。
  55成功、任意の原作直接比較1件だけskip。必須テストのskipはありません。
・純粋なModelの境界、実際の教材Controller、同梱参照、描画ログを検査。
・qa/canonical_reference.json：原作のApp.updateとApp.actionを実際に呼び出した
  合成btnp入力10経路・5197フレーム。Modelの位置・配送・観測・歩数・誤配・
  読む回数・日本語メッセージ・履歴全体・undo_count・won・pauseを各フレーム比較。
  解放/待機フレームを含む数で、人の入力フレーム数ではありません。
・原作appのROOTだけを教材qa内の一時出力先へ差し替え、手動ログが原本へ書かれない
  ようにしました。原作ファイル自体は編集せず、-Bとdont_write_bytecodeを使用。
・qa/source_provenance.jsonに全原作ファイルの事前SHA256を記録。
  採取と直接比較の前後で全ファイルのハッシュ・集合が一致しました。

比較した主な規則
・全地形・出口・記号・対象・区間・案内板の範囲が原作Cと一致。
・道外への移動は位置/歩数/表示/履歴を変えず、案内メッセージのみ変更。
・成功した一歩でだけ表示を消去。待機では表示が期限切れにならない。
・Vは全出口、板は自身の番号集合、出口はその番号だけを表示。
・板を読んでも配達しない。観測と配達済みは別のset。
・出口へ立つだけでは表示も配達も起こらない。Spaceが必要。
・誤配回数に上限なし。誤配の位置から継続。誤配出口で再Spaceなら再加算。
・配達済み出口の再確認は誤配ではない。二通の順番は自由。
・無読で葉→月は16歩、月→葉は20歩。全部配達した場所で終了。
・終了後の通常入力は停止。Zで終了を取り消し、Rで同配置を初期化できる。
・履歴のsetはコピー。無効操作は履歴へ追加しない。undo_countは戻すごとに増加。
・実Controllerの押し始めのみ入力、同時入力の優先順、Pの休憩、休憩中R/Z無効。
・固定seed 8008による2500操作も含む。乱数はテストだけで通常ゲームにはない。

実Pyxel描画
・qa/render_runs.json：Pyxel 2.9.9 headlessで22実行、すべて終了コード0。
・5段すべての初期画面と、17の意味のある到達状態をPNG/JSON/logで保存。
・PNGは480x360を2倍で保存した960x720。模型で描いた代用品ではありません。
・各イベントの状態と最終状態を実Controllerに再投入して照合。
・qa/visual_inspection.json：全22枚を目視確認。
  地形の存続、記号の表示/非表示、注文、板の範囲、配達済みチェック、誤配、
  二通完了、undo、休憩を確認。初回点検で記号と人物帽子の重なりを見つけ、
  記号を箱の上側へずらして全21枚を再描画・再点検しました。
・contact_*.pngは目視用の縮小コンタクトシート。原画像自体は加工していません。

独立実行とパス
・qa/isolation_runs.json：各.pyを一つだけ日本語・空白を含む別フォルダーへコピー。
  smokeとリプレイを別cwdから起動し、5本×2=10実行すべて成功。
・リプレイの場合だけ、その1入力JSONを明示指定。ほかの段、原作、画像、絶対パス依存なし。
・10実行とも初期/到達PNGのバイトと最終状態が正規の検査結果と一致。
・配布物コピーの標準テストも別cwd、原作環境変数なしで成功。
・PYTHONIOENCODING=cp932をLinux上で模擬。WindowsのGUI検証ではありません。
・.py/.json/.txt/.mdはUTF-8。テキストI/Oはencoding='utf-8'を明示。

再現
このフォルダーで、準備済み.venvのPythonを使用します。
   python -B test_stages.py
   python -B qa/run_renders.py
   python -B qa/run_isolation.py
任意の直接原作比較はREADME.txtのORIGINAL_008_DIRを設定してください。
原作参照の再採取：python -B qa/build_reference.py "/path/to/008_fading_footprints"
整合性検査：python -B qa/verify_freeze.py
再採取・再描画はqaを更新するため、配布版のコピーで実行してください。
freezeは検証済み配布物のハッシュであり、改造後の一致は要求しません。

権利と省略
原作LICENSEを完全一致でコピー。5本の先頭にも原文全文を保持。
原文のOFL参照先も同梱しますが、Noto字形データは使用していません。
A/B・別配置・モード切替・日本語描画・F12・GIF・常時手動ログは省略。
省略と段階ごとの差はlesson_meta.json、LESSON.md、README.txtへ明示。

未検証・区別
人の試遊、実OSキーボードイベント、Windows/macOS GUI、ブラウザ実行、音声出力は未検証。
実Pyxel headless成功から、これらの成功や面白さを推論していません。
原作の8テストと既存/新規の原作自動デモは別検査で、上記56件や22枚へ合算していません。
公開、Sites変更、ブラウザ内で遊べるという表示は行っていません。

独立レビュー後の修正（2026-10-05）
・02だけ、出口以外でSpaceを押した案内を「Use SPACE at an exit.」へ変更。
  未導入のVでの読む操作や案内板を示唆しないようにしました。
・test_stage_two_non_exit_space_names_only_exitを追加。
  実ControllerでSpaceを押し、案内文だけが変わり配送・位置・歩数は不変と確認。
・qa/02_non_exit_space_inputs.jsonを実Pyxelへ入力し、PNGの表示を目視確認。
・原作直接比較を含む56テスト、原作なしコピー55成功/任意1skip、
  日本語/空白パス・別cwdの10実行を再検査。01/03/04/05の.pyは変更なし。
