受注下書きの数量欄・応答確認教材 R40

このZIPは架空M40-v1と、著者が作った6合成Responses subsetを含みます。
OpenAI/実LLMの出力ではなく、API呼出し・課金・会社への送信はありません。
R40-01の拒否文は合成です。この安全な原注文を実モデルが拒否したという記録ではありません。
R40-03のquantity="2"は故意に型を壊した入口防御の例です。
正常なstrict Structured Outputsがこの型違いを返すという仕様・実測を主張しません。

最初に見るもの
1. original-order.txt：原注文P40・2箱、納期相談中。
2. fixtures.json / expected-cases.json：6合成応答と期待するローカル結果。
3. lesson.html：ローカルの教材画面。R40-01..06のボタンで元応答と結果を比較。
4. hold-ticket-blank.txt：自社の実値を書く7欄票。

再実行
Python 3.9以上。標準ライブラリだけを使用します。
ZIPを別の空フォルダへ展開し、そこで次を実行してください。
  python3 offline_check.py
6例と追加防御例を読み取り、JSON結果を標準出力へ出します。
Node.js 18以上も使う場合：
  python3 offline_check.py --node /absolute/path/to/node
Node.jsは別言語の同6例/共通防御例照合と構文確認にだけ必要です。
ブラウザ表示を開くだけならNode.jsは不要です。
必要なら展開先で python3 -m http.server 54890 --bind 127.0.0.1 を実行し、
ブラウザで http://127.0.0.1:54890/lesson.html を開きます。空きポートへ変更可。
これは手順の説明です。作者は今回ブラウザ実操作をしていません。

処理の順序
全体のstatus/error/incomplete_details → output内の種類 → message/contentの固定範囲
→ refusalまたはoutput_text → ローカル4欄の契約 → 元の4値との照合。
incomplete/refusalで注文を解析せず、元値の数量を応答へ補わず、0箱を作りません。
R40-05は先頭reasoningを飛ばしてmessageを選ぶ例です。
reasoning.summaryの意味を採用したり、思考の詳細を取得したりする教材ではありません。

固定契約と限界
assistant message1件/content1件のみ。任意個のreasoning(summary配列)以外の
output種類、複数候補、途中受信、tool callなどは扱わず保留します。
これは全Responsesがこの数で返るというAPI仕様ではありません。
order-contract.jsonは自社教材専用。APIへ送るJSON Schemaではありません。
PythonはJSONの重複キーを追加で拒否します。JS JSON.parseはその拒否を保証しません。
ブラウザ版は固定6ファイルの比較用です。任意入力の本番validatorへ流用しないでください。
入力が壊れた防御例の通過は、実モデルの精度や拒否率を測定した結果ではありません。
実LLM/API、実ブラウザ・他engine/端末、本番連携、会社受領/正式受注/承認、
clipboard、読者理解、業務効果は未測定です。
希望日のnullは形式上の値なしです。納期未定という意味は原文と照合します。

期待と実行記録
expected-cases.jsonは著者が定めた期待です。
execution-python39.json / execution-python312.json / execution-node.jsonは、
著者のローカル有限実行の実出力です。独立査読/画像/実機PASSではありません。
公式の根拠と必要節はsource-reading-notes.jsonを参照してください。
原注文と元応答は保存したまま、会社での採用・再依頼・再開条件を担当へ確認します。
