095 忘れもの列車 / 教材QA

範囲
原作A「青いリボンの手帳」、三時刻・三両・三人・七記録。
05のState/stepと通常調査/証拠帳/返却案/Undoを原作から照合。
B/C、表紙、説明、確認、保存読込、並列/タブ比較は意図的に省略。
Rは即リセット、Escは即終了。03のみ証拠帳から根拠選択する練習。
詳細はlesson_meta.jsonとLESSON.md。

検証済み
- 通常42テスト成功、原作パス未指定の任意1テストだけskip。
  qa/model_tests.txt、qa/standalone_tests.txt/json。
  原作パスを明示した再実行は43件すべて成功: qa/with_original_tests.txt。
  三時刻データ、既読、分類、根拠上限/解除、未読拒否、空一覧、矛盾の既知制限、返却、拒否、Undo、reset、終端、入力の押しっぱなしと和音、描画の副作用なし、文字範囲、snippet、diff、権利文書、CLIを確認。
- 原作参照: qa/canonical_comparison.json、qa/canonical_recheck.txt。
  3930のモデル遷移、384候補/既読状態の矛盾注記、9写真、24トレース2016行動。
  さらに18の通常画面Controllerトレース1796回の入力/解放で状態・phase・choice・履歴・応答が一致。
  原作の全ファイルSHA256を比較前後で一致確認。原作ファイルは配布にも実行時依存にも追加していない。
- 同梱qa/canonical_reference.jsonは原作から生成したfixture。原作がない配布先でも同じ試験を実行可。
  qa/provenance.jsonに原作model/controllerとfixtureのSHA256。
- 実Pyxel 2.9.9ヘッドレス21チェックポイント。初期5枚と、写真選択、読取り、全既読、空一覧、二根拠、上限、未知/既知の矛盾、拒否、0根拠/2根拠返却、Undo、終端、reset。
  各PNG/JSON/logおよびqa/render_runs.json。Python 3.12.14、SDL_AUDIODRIVER=dummy。
  実際のPyxel update/drawを使用。入力はController.feedへ合成したもの。
- 各.pyをそれ1本だけ日本語・空白のパスへコピーして、別の日本語・空白CWDから起動。
  PYTHONUTF8=0 / PYTHONIOENCODING=cp932でも相対PNGと明示UTF-8 JSONを保存。
  qa/isolation_runs.json。Pyxel初期化前に出力先を絶対化し、CWD変更の影響も防止。
- 教材だけ別フォルダーへコピーし、python -B -Sで42件成功・任意1件skip。
  原作もsite-packagesも使っていない。qa/standalone_tests.txt/json。
- 不正CLI 15例はすべてexit 2。Pyxel import前の拒否。qa/cli_invalid.json。
- 21枚の実描画PNGを6コンタクトシートで目視確認し、原作PNGも別に確認。
  qa/visual_review.jsonとqa/visual_sheets.json。追加フォントや新しいインストールなし。
- LICENSE、参照先Noto通知、Pyxel通知が原作の原文とバイト一致。qa/rights_packaging.json。
  教材はASCIIと図形のみ。Noto由来glyphsデータや追加フォントは使用しない。

原作証跡は別扱い
qa/original_evidenceに親タスク実施の19テストexit 0、自動無音Pyxelデモexit 0の記録。
frame_0350.pngはその新しいGIFの350番フレームを復号した実画面で、新しい別ゲーム実行や人の試遊ではない。
原作の19件と教材の42件は合算しない。音声デバイス警告があればログに残し、音声成功と扱わない。

未検証
人の試遊、OSキーボード入力、Windows/macOS GUI、音、ブラウザ。公開もこの担当では行っていない。

再現
python -B -m unittest -v test_stages.py
python -B tools/render_qa.py
python -B tools/verify_original.py /元ゲームの場所/095_lost_property_train
python -B tools/check_freeze.py
原作比較は任意。引数なしのverify_original.pyは明示SKIPで終了。
TRAIN_ORIGINAL環境変数を原作パスにすると任意unittestも実行可能。

フリーズ
FROZEN_SHA256.jsonは配布全ファイルのSHA256一覧と除外一覧。
qa/freeze_verification.txtが最終照合結果。QA再生成は証跡を変更するのでフリーズの再確認が必要。
