067 伝言は三文字：教材QA
検証日：2026-10-05 UTC
対象：01_sets.py / 02_draft.py / 03_send.py / 04_confirm.py / 05_two_requests.py
実行環境：cloud Linux、Python 3.12.14、Pyxel 2.9.9、SDL_AUDIODRIVER=dummy。
仕様はPython 3.11以上。Python 3.11そのもの、Windows/macOS実機GUIは未検証です。

1. 純粋モデル・合成Controller・配布整合性：34テスト PASS
再実行：python -B -m unittest -v test_stages.py
今回の実行は指定済み既存Pyxel仮想環境を使用。新規インストールなし。
全文ログ：qa/model_tests.txt。
・全候補からの積集合、順序非依存、空集合、相手で異なる意味
・01の無制限トグル実験と02の3枚上限、重複防止、位置削除
・03の送信時だけ消費、送信と返事、空送信、03での確認・追伸の未実装境界
・04/05の1文字追伸、2回上限、候補ゼロ時の追伸拒否、一意だが違う用事の拒否
・全文確認の追加2往復、未送信の札は非消費、送信済みの札は消費したまま
・工房→受付の意味表変更、2件共通在庫、各結果の受信者・目標・個別往復
・候補・在庫・相手・往復・追伸・結果・成功状態を含むUndo、無効入力の履歴非追加
・無入力、押しっぱなし、同時押し、全キー解放、R後の空履歴、成功後のUndo
・教材に記載した実操作列、使えない段階のCLI入力拒否、実コード断片の一致
・固定requirements、隣接差分一致、5段階schema、明示UTF-8のtext IO
合成Controller試験は実際のOSキーボードイベントの試験ではありません。

2. 原作B・通常規則との直接比較：PASS
原作model.pyのLEVELS[1]（067-B-g1）を読み取り専用で使用。-Bでpyc出力なし。
原作model.py SHA256：54bf161d056f41432afece749c4b8d76b6747a560622fc3ce11cb1fe7bb7b5a3
直接比較の前後でこのファイルのhash不変を確認。
・LEVELの全データ（日本語の名前・用事・意味集合・ヒント・目標）一致
・両受信者×全256札部分集合＝512解釈一致
・両受信者について、順序付き1〜3枚の初回下書き全400通りずつを列挙
・その初回送信後に合法な1文字追伸の全分岐を2回まで列挙
・受付の単独列挙は工房をsafeで完了して入り、原作と同じ全在庫から開始
・さらに8本の手書き完全経路と、seed 6705の200本×50入力（Undo・拒否・終了後を含む）
合計1,385入力列、15,673個の操作後状態が05と完全一致。理由と履歴長も直接照合。
通常テストは同梱fixtureの各全状態SHA256と理由を照合します。
03/04は工房の最初の完了までの導入部分を同じfixtureで照合します。
04は1件でWONになる意図的縮小、01/02はプレビュー実験なので最終モデルとの同等性は主張しません。
結果：qa/canonical_comparison.json。再実行用参照：qa/canonical_reference.json。
原作ファイルがなくても通常テストは全件動きます。直接比較tools/verify_original.pyだけが任意の原作を必要とします。
有限の入力族と固定seedの比較です。無限に可能な編集・Undo履歴の数学的証明ではありません。

3. 実Pyxel headless描画：15シナリオ PASS
tools/render_qa.pyから実Pyxelを起動し、実際のController.tickへ合成キーを渡しています。
PNGはdrawの出力。コマンド・終了コードはqa/render_runs.json、フレームと全操作後状態は各JSON。
全5本の初期画面：12フレーム、操作0、tick 0、下書き0。
01_intersection：灯＋磨の候補1
02_erased：3枚から2番目の青を外し、灯＋磨
03_sent：2枚送信、在庫6、候補1、往復1
04_post_win：1文字の初回＋1文字追伸、往復2で1件成功
04_wrong：候補3は依頼1と違うので未完了
04_post_limit：曖昧なまま追伸2回、その後の追加を拒否
05_reception：工房を完了し、受付の意味表・目標3・残り在庫へ遷移
05_won：2件成功、往復2、残り4枚、受信者別の結果を表示
05_undo：最後の確認を戻し、受付の候補3・送信札・往復2へ復帰
05_safe：全文確認だけで2件成功、往復4、札消費0
全15PNGを最終描画後に実際に開いて観察済み。
文字の切れ・表の列位置・現在の相手と目標・札の意味・使用済み表示・候補・結果欄を確認しました。
初回の観察で表ヘッダー位置と使用済み札の文字の明るさを調整し、全画面を再描画・再確認しました。
音声処理は設計上ありません。dummy audio driverを使い、音が聞こえたとの主張はしません。

4. 単独起動と同梱テストの独立性：PASS
全5本をそれぞれ空の一時フォルダーへ1本だけコピーして、実Pyxelで12フレーム起動。
相対出力指定relative.png / relative.jsonの作成も確認。qa/isolation_runs.json。
教材一式を別の一時フォルダーへコピーし、元のゲームなし・site-packagesを読み込まない-S実行でも34テストPASS。
この検証はqa/standalone_tests.txtとqa/standalone_tests.json。

5. 再現性・権利・範囲
全5本、テスト、検証補助に原作のMIT全文を保持。LICENSEも原文通りです。
原作LICENSEのNoto例外文は原文保存ですが、この教材にNoto字形・フォント資産は含めません。
Pyxelは外部依存。音声素材・第三者画像素材・非公開サービスは使っていません。
qa/provenance.jsonに原作の参照元とhash、保持範囲と省略機能を記載。
qa/freeze_manifest.jsonに配布ファイルのSHA256。tools/check_freeze.pyで確認できます。
原作は変更していません。作業と出力はこの教材フォルダー内、隔離検証時だけ一時フォルダーを使用。

6. 未実施
人間の楽しさ・難易度・読みやすさ評価、Windows/macOSの実GUI、Python 3.11実行、
OSネイティブのキーボード入力、ブラウザ操作、音声評価、Site公開、ユーザーPC操作。
原作側の既存テスト数や動画の結果は、今回の教材の検証件数に合算していません。
