077 からくり郵便室・教材QA / 2026-10-05 UTC

対象: 5本の独立教材。最終04/05は原作B「四つの小包」の通常同期モード。
環境: クラウドLinux / Python 3.12.14 / 実Pyxel 2.9.9。
仕様はPython 3.11以上。3.11実インタプリター、Windows/macOS実GUIは未確認。

純粋規則・合成入力: 41テスト成功（qa/full_tests.txt）。
同じ41件を原作のない配布単独の日本語・空白フォルダーでも成功（qa/standalone_tests.txt）。
文字コードの省略値をCP932へ置き換えたLinux回帰も41件成功（qa/cp932_tests.txt）。
3回とも同じテスト群であり、123種類のテストがあるという意味ではありません。
原作の18テストと原作側の自動デモは教材の件数へ含めていません。

比較の範囲:
原作B通常モードのカード4^3×札4^4 = 16,384構成を有限列挙。
各構成の設定済みEDIT、開始後、終端までの全tickを正規化JSONへ変換しSHA-256で比較。
04/05のそれぞれで16,384構成、58,952 tick遷移がすべて一致。成功構成は2通り。
照合項目はcards、labels、t、next_id、queue、tables、deliveries、paths、status、moves、waits。
表示用reasonだけは教材の案内文へ短縮したため比較から除外。
03の固定正解構成も同じ期待値と一致。01/02は時間・占有を省いた模型なので同期同等性は主張しません。
原作A/C、flow比較モード、元のController/描画、不正外部入力全般の同等性は対象外です。
qa/original_B_fixture.jsonは原作model.pyから生成した期待値。比較時に外部原作パスは不要です。
必要ならqa/generate_original_fixture.pyへ--original-directoryで原作フォルダーを明示して再生成できます。

主な規則確認:
4カード、木の台・箱番号、全6便属性と到着時刻、同刻空き台の不使用、新到着の再処理防止、
番号単位の保存則、宛先照合、誤配刻の原子的反映と停止、13刻成功、32刻境界、編集制約、
判定カード上限、重複札合法、全状態Undo、開始を戻して編集、拒否操作の履歴不追加、512操作上限。
下流2台の占有や32刻の境界は検査用Stateを注入したテストも含み、通常到達局面と区別しています。

実Pyxel自動描画:
全5段階の初期画面と意味のある到達点、計10プロセスが成功。10PNGを目視確認しました。
画像は800×720。文字切れ・台/箱の重なり・選択枠・属性凡例・状態・操作案内を確認。
01: 青・重さ2をWEIGHTでLEFTへ。02: 同便をA→C→箱3へ。
03: 2刻目、A空・Bに便1・待ち列2/3。空いたAへ同刻に入れないことを表示。
04: 編集キーで正解配置を組み、13刻で6便正配DONE。
05: 同じ成功からX、12刻RUN・配達5件・Bに便6へ復元。
各PNGは実PyxelのupdateからApp.controlへ合成キー集合を入力した描画です。OSキー操作ではありません。
同一プロセスで終了直前のStateをJSON出力し、純粋Controllerの期待状態と照合済み。
詳しい記録はqa/render_results.jsonおよび各initial/checkpoint PNG・ログ。

単体隔離:
各.pyをそれぞれ日本語・空白フォルダーへ1本だけコピーし、別cwdから実Pyxelで起動。
全5プロセス成功、5PNGと状態を保存。qa/isolation_results.json。
コピー先に他の教材・素材・モデルはなし。既存Pyxel実行環境は利用しました。

最初のQA補助側ではpyxel.quit後にPythonへ戻る想定で状態ログを待ち、PNG生成は成功したものの
状態未取得として失敗を検知しました。終了前にflush付きで状態を出すよう修正し、全描画・隔離・規則試験を再実行。
初回の失敗記録はqa/initial_capture_failure.txt。成功判定へ混ぜていません。

権利・来歴:
原作model/controller/app/README/LICENSE等は読み取りのみ。開始時のハッシュと終了時を照合。
qa/original_sha256.jsonとqa/provenance.jsonに由来・範囲・ソースハッシュを記録。
LICENSEは元のLICENSE.txtと完全一致。5本の先頭コメントにも全文を保持。
画面はASCII文字だけでNotoの字形データは同梱しません。元の第三者字形例外は原文のまま保持。
UTF-8テキスト入出力を明示。各.py、テスト、期待値に絶対ローカルパス依存はありません。

未確認:
人による面白さ・学びやすさ、ネイティブOSの窓・キー、Windows/macOS GUI、ブラウザー、音声再生。
音声は設計上ありません。SDL_AUDIODRIVER=dummyを音声再生成功とは数えていません。
画像は自動・合成入力の検証記録で、人のプレイやブラウザーゲームの証拠ではありません。

再実行:
python -B -m unittest -v test_stages.py
python -B run_qa.py
後者は既存のqa画像・ログを更新します。再実行後は凍結ハッシュが変わることがあります。
FROZEN_SHA256.jsonはQA完了後に作り、自分自身を除く配布ファイルのSHA-256を記録しています。
