CONFIDENTIAL | キヨさん照会回答 | 2026-07-23(v1.5=2026-07-25 追記)

SPI模試 コンテンツ&供給システム 仕様書 v1.5
― 能力検査・性格検査・供給基盤・そして未解決の課題 ―

キヨさんからの「SPI模試の仕様」照会への回答。コンテンツ(能力検査・性格検査)/供給システム(API・問題バンク配信基盤)/現時点の課題を一枚にまとめました。課題は隠さず全件記載しています(§4に23件)。記載はすべて 2026-07-23 時点の一次現物(本番URL実測・コード・データファイル)で裏どりし、確認できなかったものは unknown と明記しています。
v1.3(07-23夕方 更新)=本日の改修で解決した項目に「解決済み」を付け、実測で判明した数値の訂正と、検証で新たに見つかった課題を追記しました。
v1.4(2026-07-24 追記)=「Phase C=配信のサーバ一本化」に着手(当時ブランチ段階)。
v1.5(2026-07-25 追記)=Phase C を本番反映完了(LIVE)。あわせて第三者監査(GPT系)で見つかった公務員解説の選択肢番号バグを恒久修正し、再発防止の配信前ゲートを常設しました。詳細は §1 末尾の追記ブロックをご覧ください。外部提供API(B)の仕様・キーには一切影響しません(別線・変更なし)。

📌 3行サマリー
目次
  1. 全体像 — 何が、どこから、どう配られているか
  2. コンテンツ仕様(能力検査・性格検査・SCOA・公務員)
  3. 供給システム仕様(正本リリース・出題サンプラ・API)
  4. 課題 — 全23件(隠さず全件)
  5. キヨさんと握りたい判断
  6. 検証エビデンス(再現手順)
  7. 2026-07-23 の改修で解決したもの

1. 全体像 — 何が、どこから、どう配られているか

SPI模試は「①問題を作る」「②正本として版を固める」「③配る」の3層で構成されています。現在配信経路は4系統が並存しており、これが§4の課題の主因にもなっています。

生成層 | 問題をつくる
spi_generator(Python・自社生成器)
正答一意性ゲート/grounding検査を通した問題を量産する
spi-questions.full.v2.json
上流フルバンク 7,537問(ここまでが素材。まだ版としては固まっていない)
正本層 | 版として固める
release_build.py
単元マスタ/試験ブループリントを結合し、4フィールドを焼き込んで版を組み立てる
serving/配信用。答えを含まない
_answers/答えと解説だけを分離
passages/長文本文。sha256をファイル名にする content-addressed
manifest.json全ファイルのsha256と件数を事前集計
publish_release.py
R2へ版ごと投入(イミュータブル=一度置いた版は書き換えない)+ current.json を CAS で切替
R2: educare-question-bank
serving + manifest + current.json
R2: educare-question-bank-answers
_answers のみ・別バケットに物理分離
配信層 | 全経路が正本(A)へ一本化済み(2026-07-25 実測)
A正本・唯一の出題元
出題worker
spi-questions.komuin-sukima.workers.dev
R2の正本を読んで出題する(重み駆動サンプラ)。自社フロント(C)(D)の唯一の出題元。出題セットには署名トークンが付き、採点はサーバ側(答え・解説はセット応答に含めない)。
  • GET /api/exam/set?exam=&count=(出題セット)
  • POST /api/grade/finish(サーバ採点)
  • GET /api/spi/pool/stats
(C)(D) から本番配線済み(実測)
B正本と同世代
SPI Platform API
(外部提供用)
educare-cbt-ingest.komuin-sukima.workers.dev
テナント別Bearerキー・答えは一切返さない・OpenAPI 3.1公開。今回のフロント一本化とは別線・変更なし
  • POST /v1/sessions
  • POST /v1/sessions/{id}/questions
  • PUT .../answer
  • POST .../result
キヨさんが叩けるのはこれ(tenant=kiyo 発行済み)
C(A)へ配線済み
自社フロント
Web体験模試
educarelog.net/spi-taiken/
埋め込みバンクを全廃し、開始時に (A) から取得。受験用JSチャンクは 16.4MB → 約55KB(本番実測)。採点はサーバ。ブラウザへ答え・解説を配らない(§4-1/§4-8 を構造的に解消)。
現行版 qb-r2-20260724d を (A) 経由で配信
D(A)へ配線済み
LINE内受験
LIFF版
educare-poc.komuin-sukima.workers.dev
(C)と同型で同梱バンクを全廃し (A) へ配線。SPAバンドルに問題IDの同梱ゼロ(本番実測)。api/exam/setapi/grade/finish を叩く。
旧5,343問の同梱スナップショットは解消
正本(A)から同世代を配っている ※ 2026-07-24 以前は (A) が未配線・(C)(D) が古い同梱スナップショットでしたが、Phase C で解消しました。
系統実体いま何が起きているか(2026-07-25 実測)
(A) 出題worker
spi-questions
spi-questions.komuin-sukima.workers.devfact稼働中・自社フロントの唯一の出題元。現行版 qb-r2-20260724d。本番で出題セット取得→60秒床→終了時採点を実測し、セット応答に答え・解説が含まれないことを確認。
(B) 外部提供API
SPI Platform API
educare-cbt-ingest.komuin-sukima.workers.devfact稼働中。/healthz 200・/openapi.json が OpenAPI 3.1.0 を返す。キヨさんが叩けるのはこれ。今回のフロント一本化とは別線・仕様/キー変更なし。
(C) 自社フロント
体験模試(Web)
educarelog.net/spi-taiken/fact稼働中・一般公開。埋め込みバンクを全廃し (A) から取得questions-api チャンクが (A) の api/exam/setapi/grade/finish を叩く・受験用チャンク約55KB・問題IDの同梱ゼロを本番実測)。
(D) LINE内受験
LIFF版
educare-poc.komuin-sukima.workers.devfact稼働中。同梱バンクを全廃し (A) から取得(SPAバンドルが (A) の api/exam/setapi/grade/finish を叩く・問題IDの同梱ゼロを本番実測)。

※ 4系統すべてが正本 (A/B は worker、C/D は (A) 経由) から同世代を配っている状態を本番実測で確認しました。かつての「正本と実配信のねじれ」(§4-1/§4-2 の直接原因)は解消されています。

✅ 解消済み:正本と実配信のねじれ(旧・最重要の構造問題) かつては (A) が実装済みなのに未配線で、一般ユーザーが受ける (C)(D) が正本から切り離された古い同梱スナップショットで動いていました。Phase C で (C)(D) を (A) 出題worker へ本番配線し、埋め込みバンクを全廃。答え・解説はブラウザへ配らず、採点はサーバ側に一本化されました(§4-1/§4-2/§4-8 を構造的に解消)。本番URLの実測で裏どり済みです。
✅ Phase C = 配信のサーバ一本化(2026-07-24 着手 → 2026-07-25 本番反映完了・LIVE)

上の (C)(D) が抱える2つの構造欠陥 ―― ①ブラウザに問題バンクを丸ごと同梱(16.4MB・世代ズレ/§4-8)②答え・解説をクライアントに配って採点もクライアント側(§4-1) ―― を、フロントを (A) 出題worker へ配線し直すことで根絶しました。敏さんの決裁「答えはクライアントへ渡さない・採点はサーバ・オフライン非対応でよい」に基づく設計で、全工程を本番反映済みです。本番URLで実測(出題セット取得→60秒床→終了時採点)し、出題セット応答に答え・解説が含まれないことを確認しています。

工程状態(2026-07-25)内容
C-0 採点線の新設LIVE本番反映済答えを読むのは非公開の採点専用worker(qb-scorer)だけにし、公開workerからは答えバケットのバインディングを物理的に外しました。出題セットに署名トークンを付け、「配られたセットの問題しか採点を受け付けない」ことで、§4系で指摘された正答の機械的な一括抽出(オラクル)を構造的に遮断。模試モードは終了時、単元練習モードのみ回答直後に正誤・解説を返します。第三者監査(GPT系)が1度差し戻し→是正→2回目で全項目クリア。
C-1 Web体験模試(C)のfetch化LIVE本番反映済埋め込みバンクを全廃し開始時に (A) から取得。受験用JSチャンクは 16.4MB → 55KB に激減(実測)。採点はサーバの採点APIへ。監査指摘の「通信失敗時に採点要求を再送し続ける」実バグは「失敗時は明示エラーで停止(再送しない)」に是正済み
C-2 LINE内受験(D)のfetch化LIVE本番反映済(C) と同型で LIFF 版の同梱バンクを廃止し (A) へ配線しました。C-1 の是正型を横展開。これにより (C)(D) の古いスナップショットは解消され、自社フロントは (A) 出題worker+サーバ採点の1経路へ統合されました。

※ 本番反映はデプロイゲート経由で完了しています。キヨさんが使う (B) 外部提供API には影響しません(別線・変更なし)。現行の正本リリースは qb-r2-20260724d です。

✅ 解説の選択肢番号バグを恒久修正(2026-07-25・第三者監査 Blocker-1)

Phase C 本番反映後の第三者監査(GPT系の実受験チェック)で、公務員ラインの解説文が、答え自体は正しいのに「選択肢3は…」の番号が正答位置とずれ、範囲外の「選択肢0」を参照する不具合が見つかりました(採点は正常・解説文だけ誤り)。原因は、正答位置の偏りを直す並べ替えの際に、元の解説が問題ごとに「0から数える/1から数える」を混在させていた(1問の中で混在するものすらあった)ため、番号だけが取り残されたことです。SPI本体・SCOAは番号参照を使っておらず無傷でした。

対策内容
解説の番号非依存化「選択肢3」のような番号参照そのものを廃止し、選択肢の本文を引用する形(例:「〇〇である」の肢は誤り)へ機械変換。並べ替えても壊れない構造にしました。公務員538問を変換し、バンク全体の番号参照はゼロ(答え・選択肢の中身は変更なし)。
配信前ゲートの常設版を組む段階で、解説に選択肢の番号参照が残っていないか+引用が答え・選択肢と一致するかを機械照合し、1問でも不整合があれば版を出せない(fail-closed)ようにしました。今後の生成でも番号参照は受け付けません。
本番実測本番の出題→採点を実際に叩き、解説に番号参照0行・引用型解説で配信されていることを確認済み。系譜台帳(版の履歴)も更新済み。

※ あわせて、図から積み木の総数を一意に数えられない「積み木数え」40問(判断推理・空間把握の一部)を暫定で配信除外しています(図の作り方の改修は別工程)。この不具合は能力検査の非言語=(B) 外部提供APIにも同じ問題製造基盤を使うため、上記の番号非依存化とゲートは外部提供分にも同様に効きます(キー・エンドポイントの仕様変更はありません)。

2. コンテンツ仕様

2-1. 能力検査バンク(正本・7,537問)

fact全問が自社オリジナル生成(source: original/educare が7,537件中7,537件)。既存教材の複製は含みません。全問5択・全問解説ステップ付き(平均5.0ステップ・欠落0件)。

分野トピック問題数サブパターン(=出題型)
非言語
6,765問
推論1,00010型:順序関係/位置関係/対応関係/リーグ戦/発言推理/正誤推論/命題と論理/数値推論/平均・順位推論/物の個数
旅人算5005型:出会い/追いつき/周回/通過算/流水算
表の読み取り5005型:合計・平均/増加額/増減率/構成比/比較・順位
損益算4004型:基本損益/割引・値引/原価or定価の逆算/複数個・複数商品
仕事算4004型:基本(2人共同)/3人以上/途中で人数変動/水槽
確率4004型:基本確率/余事象/独立試行/反復試行
整数の性質4004型:約数倍数/素因数分解/剰余/N進法
割合と比3704型:増減率/比例配分/連比/食塩水濃度
場合の数3444型:順列P/組合せC/円順列/重複順列
集合3003型:2集合/3集合/キャロル表
代金の精算3003型:割り勘(余り含む)/立替精算/複数人立替の最終精算
分割払い3003型:頭金+均等分割/手数料込み総額/分割回数を求める
鶴亀算3003型:基本(頭と足)/3種類/得点型(正解+・不正解−)
平均算3003型:加重平均/平均から合計や個別値/平均の増減から個別値
ニュートン算3003型:牧草と牛/給排水型/行列(窓口処理)
料金割引2503型:団体割引/セット割引/複数プラン比較
年齢算2323型:現在年齢を比から/何年後に○倍/年齢差一定の応用
時計算1693型:長針短針の角度/針が重なる時刻/針が直角or一直線
言語
772問
文の並べ替え2002型:正しい順序選択/N番目選択
空欄補充(接続詞)1602型:接続詞補充/論理関係補充
語句の意味1202型:文脈語義選択/近義語選択
二語の関係961型
熟語の成り立ち841型
語句の用法801型:下線部用法選択
文章理解32空欄補充12/内容合致・趣旨14/指示語6(長文14本・本文はsha256参照で別管理)

難易度分布

分野難易度12345
非言語1,1742,3482,1857093496,765
言語2437837000772

課題言語は難易度4・5が1問も存在しない(§4-6)。

解説の構造

解説は自由記述の文章ではなく5ステップの定型構造を持ちます(実測平均5.0ステップ)。①何の単元か → ②定義・考え方の言語化 → ③立式と時短のコツ → ④答え → ⑤ありがちミス、という並びです。この構造化により、後段のAI講師・図解生成の「燃料」として機械的に扱える設計にしています。

実例(損益算・難易度3):
「これは損益算です。」→「定義は連続する割引は、元の定価ではなく直前の価格を基準にします。⇒つまり、何を1単位として見るかを先に固定して下さい。」→「計算は2100円に80%、次に90%をかけ、最後に200円を引きます。時短のコツは、式に入れる前に単位をそろえることです。」→「答えは1312円です。」→「ありがちミスは、割引率を足して一度に引く、または値引きを最初に引くことです。」

2-2. 性格検査(ビッグファイブ方式・45問)

fact本番 educarelog.net で稼働中(本日、配信中のJSバンドルから45項目の実データを直接抽出して確認)。受験モードは体験/本番/単元練習/性格検査の4つで、性格検査は無料会員登録(LINEまたはGoogle)で解放される設計です。

項目仕様
設問数・形式45問/5件法リッカート(「まったく当てはまらない」〜「非常に当てはまる」)
因子(ビッグファイブ)開放性8問/誠実性10問/外向性8問/協調性10問/情緒安定性9問
SPI側面へのマッピング各因子スコアを重み付けして行動的側面・意欲的側面・情緒的側面・社会関係的側面の4側面へ変換(項目側にも aspect タグを保持:行動的12/意欲的8/情緒的12/社会関係的13)
逆転項目12問(スコア計算時に 6 − 回答値 で反転)
ライスケール(虚偽検出)5問。合計が閾値20を超えると「回答の一貫性に注意」の警告を結果画面に表示
スコア算出因子別平均 → 平均3・SD1を基準に偏差値換算(20〜80でクランプ)
結果表示レーダーチャート+因子ごとの「強み/注意点/面接でのヒント」テキスト
計測1問回答ごとに personality_item_answered、完了時に personality_survey_complete(ライスケール合計・警告フラグ付き)を本番ingestへ送信。CBTイベントの domainpersonality
免責UI上に「ビッグファイブ理論に基づく簡易性格診断であり、採用結果や本番の判定を保証するものではない」旨を明示
性格検査についての正直な位置づけ 本家SPIの性格検査は項目内容も尺度定義も非公開の商用IPです。したがって本実装は複製ではなく、公開理論であるビッグファイブで独自に45項目を作り、それをSPIの4側面へ重み付けで近似マッピングした独自モデルです。「本番の予行演習として画面と設問形式に慣れる」用途では機能しますが、「本番のスコアを予測する」用途には現状耐えません。以下、ご照会の4点に個別にお答えします。

■ ご照会①:項目は公開検証済み尺度(IPIP/TIPI-J等)ベースか、自作か

結論:自作です。公開尺度を土台にはしていますが、項目文そのものは既存尺度の翻訳・翻案ではなく書き下ろしです。

■ ご照会②:信頼性係数などの確認はされているか

結論:されていません。未実施のまま公開しています。

■ ご照会③:スコアの基準(何との比較か)

結論:受験者集団との比較ではありません。「5件法の理論的中点」との比較です。ここは誤解を招きやすいので明確にお伝えします。

現行の偏差値は「規範集団のない偏差値」です 実装は次の固定式です(本番配信中のコードから抽出):
偏差値 = 50 + 10 × (因子の平均回答値 − 3) ÷ 1 (20〜80でクランプ)

「3」は5件法の理論的中点、「1」は仮置きの標準偏差で、どちらも定数としてコードに直書きされています。実際の受験者集団の平均・標準偏差は一切参照していませんし、実データから基準値を再計算する仕組みも実装されていません。

したがって「偏差値60」は「他の受験者より上位」という意味ではなく、「その因子の設問に平均4.0で当てはまると自己申告した」という意味です。全項目に「非常に当てはまる(5)」と回答すれば、母集団と無関係に一律70になります。

■ ご照会④:結果の免責表記の想定

結論:文言は既に存在し本番表示されていますが、出るのは結果画面だけです。受験前・受験中には保証を否定する文言がありません。

表示箇所現行の文言(逐語)表示条件
能力検査トップの導入カードビッグファイブ理論に基づく簡易性格診断(SPI性格検査の練習用)。タイマーなし・戻る自由・正誤なし。常時。保証否定の文言なし
受験画面バッジビッグファイブ理論に基づく簡易性格診断回答中は常時
受験画面リード文正誤やタイマーはありません。直感に近い選択肢を選んでください。戻って回答を変更できます。回答中は常時。操作説明のみで免責語なし
結果画面(唯一の実質的免責)ビッグファイブ理論に基づく練習用の自己申告プロフィールです。採用結果や本番の判定を保証するものではありません。45問完答後の結果画面のみ
ライスケール警告ライスケールが高めです。よく見せようとした回答が混ざると、面接準備に使う自己理解がずれやすくなります。ライスケール合計20以上のときのみ

当社としての想定(ご意見をいただきたい点):現状は「結果を見た人にだけ免責が届く」構造なので、受験を開始する前の画面に同等の文言を出すのが妥当と考えています。あわせて、②③の実態を踏まえて次の3点を明示する案です。

※ 有料商材として提供する場合は、上記に加えて利用規約側にも同趣旨の条項が要ります(法務レーンで別途整理中)。

2-3. 体験模試に同梱されている実バンク(6,536問)

fact一般公開中の体験模試(/spi-taiken/)は、サーバに問題を取りに行かずビルド時にJSバンドルへ同梱された6,536問から出題しています。SPIだけでなく公務員試験科目も含むのが特徴です。

系統分野問題数主なトピック
SPI系
(4,369問)
非言語3,839推論1,050/集合350/損益算・旅人算・仕事算・料金割引・割合と比・場合の数・確率・表の読み取り・整数の性質 各250 ほか
語彙500二語の関係250/熟語の成り立ち250
言語30文章理解30
公務員系
(2,167問)
判断推理955位置関係106/対応関係103/順位100/嘘つき100/試合100/方位100/命題100/空間把握134 ほか
資料解釈519実数割合144/構成比141/増加率125/指数109
文章理解351現代文191/英文160
自然科学110生物37/地学35 ほか
社会科学110経済37/法律29/政治28 ほか
人文科学/時事110/12日本史35 ほか/時事12

※ このバンクは正本(7,537問)とID体系は同じですが中身は別世代です。共通IDは3,408件ありますが、うち3,407件が別の問題を指しています(§4-1)。

公務員模試には専用バンクが無い fact公務員向け模試(komuin-webtest)はSPIと同一のバンクファイルを分野タグでフィルタして出題しています。公務員専用の問題ファイルは存在しません。さらに、試験種タグ(地方上級・警察・消防・国家一般・特別区・市役所)が付いている問題は6,536問中134問だけ(各試験種50〜72問)で、残りは試験種を問わない汎用出題です。これが意図的な設計か暫定措置かは、当社内でも記録が残っていません(§4-17)。

2-4. SCOA体験模試(未公開・リリース直前)

factSCOA(自治体で採用が広がっている総合適性検査)向けの体験模試を別ラインで開発済みですが、本番未公開(公開フラグ未反転・masterへ未マージ)。10問10分の軽量ランナーと段階アニメーション図解まで実装済みで、リリース前監査で公開ブロッカー4件が出て止めている状態です(§4-10)。

内訳(全145問・全問5択・SCOA-A形式)
尺度論理 75/数理 36/常識 34
問題型空間把握51・推論24・常識(自然科学)12・常識(社会科学)12・四則計算12・割合損益12・数列12・常識(時事)10
難易度2:39/3:63/4:43
正答位置0:31/1:34/2:33/3:18/4:29(偏りは軽微=SPI文章理解のような欠陥はなし)
体験版レシピ10問=数理3+論理3(空間は最大1)+常識4/10分
検品全数の機械検査PASS+外部AIによる抜き取り32/32一致。ブロッカー11件は在庫不足由来(正多面体型の枯渇9・時事在庫2)で誤答由来ではない

課題SCOAは言語・英語の尺度が未開発のため体験版に含まれていません(§4-18)。

2-5. コンテンツ設計の背骨 — 単元マトリクス(在庫管理システム)

「どの単元をどれだけ持っているか/本試験でどれだけ出るか」を1系統で管理する台帳を正本化しています。感覚ではなく出題実績データで補充優先度を決めるための装置です。

構成要素内容
単元マトリクス396行(数的処理88/言語7/自然科学301)。列=SPI在庫(完全一致/関連)×公務員出題頻度×出題周期×タネ状態×SCOA適用
出題実績インデックス数的処理3,977件(1994–2018・10試験種)/論文416設問(2009–2026)/自然科学200件/文章理解365行(2010–2025)=計4,958行
試験ブループリント試験種別(行政・国家総合・警察消防など)の単元重み表。重み合計=1.0に正規化。出題サンプラがこの重みで比例配分する
台帳の実体正本=Gitリポジトリ、D1(educare-content-ledger)は一方向レプリカ。全再構築方式で冪等性を担保

この台帳から出てくる示唆の例:計量図形は公務員試験で実績337回・ほぼ毎年出題(平均1.1年に1回)なのにSPI側の在庫は0問不定方程式は2変数型が約1.4年に1回、3変数型が約3.7年に1回。こうした「頻度×在庫」の突き合わせで補充計画を機械的に立てています。

3. 供給システム仕様

3-1. 問題バンクの正本 = R2上のイミュータブル版付きリリース

問題データの唯一の正本(SSOT)は、Cloudflare R2 に置く版ごとに不変なリリースです。D1・静的JSON・管理画面などのコピーはすべて「リリースIDで系譜が辿れる派生キャッシュ」に格下げしました。

設計要素仕様
バケット2本分離educare-question-bank(配信用)と educare-question-bank-answers(答え専用)を物理的に別バケットに。「配信・採点はAPI、答えは壁の裏」というIP境界を、アプリのロジックではなくデータの置き場所で強制する設計
シャード分割軸group(arithmetic/inference/verbal)× topic の直積。NDJSON形式
長文の扱いpassages/{sha256}.json と content-addressed 化。同一本文の重複保存が原理的に起きない
統一エンベロープrecord_type / schema_version / id / exam_family / scale / group / topic / subtype / bank_release_id / taxonomy_version / unit_id / mapping_accuracy / difficulty / stem / choices / passage_ref / figures / methods / family_ext / provenance
単元系譜の焼き込みリリース生成時に bank_release_id・taxonomy_version・unit_id・mapping_accuracy の4フィールドを単元マスタから機械導出して全問に付与。承認済みマッピングのみ採用し、未マップは nullunmapped と正直に記録
決定論性JSONは sort_keys, compact, ensure_ascii=false に正規化、行順はID昇順固定。同じ入力からは必ずバイト単位で同一のリリースが再生成される(2回ビルドしてバイト一致を検証済み)
完全性検証manifest に全ファイルの sha256 と件数を事前集計。さらにシャードごとに id_set_sha256(含まれる問題ID集合のハッシュ)を持ち、配信用シャードと答えシャードのID整合を機械照合
版の切替current.json を ETag条件付き更新(Compare-And-Swap)で切替。競合時は412で失敗させる。オブジェクト投入は If-None-Match: * で新規のみ許可=既存版の上書きは不可能
ロールバックcurrent.jsonprevious_release_id を保持。旧リリース本体はR2に残るので、ポインタを書き戻すだけで即座に戻せる
現行版qb-r1-20260723(本日公開・65オブジェクト/10.8MB。前版 qb-r1-20260721

3-2. 出題サンプラ(spi-questions worker)

R2のリリースを読んで実際に問題を選ぶ層です。単なるランダムではなく、試験種の出題重みに比例した配分を行います。

機能仕様
データ解決current.json(60秒TTLでキャッシュ)→ manifest.json(sha256照合)→ 該当シャード。manifestのハッシュが合わなければ即エラー
試験種重み駆動exam 指定時、ブループリントの単元重みに count × weight/総重み で比例配分。端数は重み降順に決定論的に配分
単元指定unit 指定時は mapping_accuracy = exact のみ採用(関連単元での代替はしない)。0件なら暗黙のフォールバックをせず空を返す
トピック偏り防止1トピックが出題数の30%を超えないよう上限キャップ
重複回避exclude_ids(最大200件)をクエリで受け取りステートレスに除外
既定配分無指定時は arithmetic:inference:verbal = 50:25:25(単元練習モードのみ arithmetic 100%)
障害時R2オブジェクト欠落・ハッシュ不一致・パース失敗はすべて HTTP 503。部分縮退やサイレントフォールバックはしないフェイルクローズ設計

3-3. SPI Platform API(キヨさん/INNOTH向け外部提供線)

fact本日 /healthz 200・/openapi.json(OpenAPI 3.1.0, title="SPI Platform API")配信を実測確認。Swagger UI も /docs で閲覧できます。

✅ 本日、キヨさんのテナントキーで実弾検証しました

エンドポイント一覧

メソッド/パス認証概要
GET /healthz / GET /openapi.json / GET /docs不要ヘルスチェック・仕様書・Swagger UI
GET /v1/questionsBearer問題一覧(topic/limit≤50/offset)。ページング付き
GET /v1/questions/{id}Bearer問題単体取得
POST /v1/sessionsBearer受験セッション開始。mode=taiken/honban/tanren。201+Location
GET /v1/sessions/{id}Bearerセッション状態(出題数・回答数・ステータス)
POST /v1/sessions/{id}/questionsBearer次の設問を要求。未回答の保留設問があれば200で再返却(冪等)、新規は201
PUT /v1/sessions/{id}/questions/{item_id}/answerBearer解答送信(choiceelapsed_mstimed_out)。即時正誤を返す。冪等
POST /v1/sessions/{id}/resultBearer採点確定(初回201・以降200で同じ結果)。偏差値・グレード・分野別内訳
POST /v1/scoresBearerステートレス採点(セッションを作らず解答配列を渡して採点)。domain=spi/personality
POST /v1/events / POST /ingest任意/不要受験テレメトリ受信(202)。/ingestはレガシー互換

セキュリティ/マルチテナント

データモデル(D1)

テーブル主な列
tenantstenant_id / name / api_key_hash / allowed_origins / rate_limit_per_minute / tier / calibration_optin / key_status / key_issued_at
api_sessionssession_id / tenant_id / domain / mode / topic_filter / policy_json(採用した出題ポリシーのスナップショット)/ status / created_at / finished_at
api_session_itemssession_id / item_id / served_at / selected_choice / is_correct / elapsed_ms / timed_out / answered_at + UNIQUE(session_id,item_id)
events / item_responses受験テレメトリ。domain/type/session_id/地理情報(CF由来)/ip_hash/tenant_id。設問単位の正誤・所要時間を item_responses に蓄積
questionsAPI側が持つ問題テーブル(answer・explanation_stepsを平文保持=サーバ内部専用)

3-4. 自社フロントの配信方式(現状)

fact体験模試は問題バンクをビルド時に取り込み、ブラウザへ丸ごと配布しています(JSバンドル1本=展開16.4MB/gzip転送1.6MB/6,536問・答えと解説を含む)。実行時に問題APIを叩くコードはゼロ件です。サーバ通信は「LINE認証」と「受験結果の送信」のみ。

4. 課題 — 全23件

重大度は当社評価です。2026-07-23 に解決した項目は §7 にまとめています。

CRITICAL4-2. 実際に配信しているバンクが正本から切り離されている(正本の二重化)

✅ 解決済み(2026-07-25・Phase C)体験模試(C)・LINE内受験(D)を出題worker(A)経由の配信へ本番切替し、ビルド時同梱を全廃しました。以降は全経路が正本(R2版付きリリース)から同世代を配信します。本番URLの実測で裏どり済み((C)は受験用チャンク約55KB・(D)はSPAに問題ID同梱ゼロ)。以下は切替前の記録です。

factR2の版付きリリースを唯一の正本にする設計は完成し、それを読む出題workerも本番稼働していますが、一般ユーザーが受けている体験模試はそこを見ておらず、ビルド時同梱の旧スナップショットで動いています。正本にしか無い問題が4,129問、フロントにしか無い問題が3,128問あります。

影響:正本を直しても本番の受験体験は直りません(§4-3の正答位置リークも、正本を直しただけでは公開面に反映されない)。改善のリードタイムが常にフロントの再ビルド・再デプロイ待ちになります。

是正案:体験模試を出題worker経由の配信へ切り替える(設計・実装は済んでおり「配線」だけが残っている状態)。切替までの暫定として、同梱バンクを最新リリースから機械生成する。

HIGH4-4. 公開中バンクに重複問題が3割ある

⚠️ 初版の数値を訂正します(v1.3)初版で「重複3割」と書きましたが、これは問題文の冒頭60字が一致するものを数えた値で、過大でした。同じ基準では正本7,537問でも500件が該当し(うち推論476件は数値だけ違う正常なパラメトリック問題)、出荷を止める基準としては誤検知が多すぎます。厳密に測り直した結果は下表です。
判定基準正本7,537公開面6,536
問題文+選択肢が完全一致(=真の重複)0問6問
問題文が完全一致(選択肢違い)0問799問
冒頭60字が一致(同型の数値違い)500問1,855問

fact体感の主犯は実在します。「二語の関係」250問は問題文ユニークがわずか94で、同一の語ペア(日照:発芽/大豆:豆腐 など)が6回ずつ、選択肢だけ差し替えて登場します。問題文が完全一致する重複799問の内訳は熟語166/二語156/英文120/現代文92が主で、サーバ側の分類ミスではなく公開面のバンクが旧世代だったことが機序でした(正本側の二語は96問で健全)。

是正案:§4-2の配信切替で自動解消。暫定対応なら同梱バンクから重複を除去。

HIGH4-5. 受験形式(テストセンター/WEBテスティング/ペーパー)の出し分けができない

fact正本7,537問すべての methods[testcenter, web, paper] の一律値です。一方、外部10ソースの調査では「二語の関係」はテストセンター専用(WEBテスティングでは出ない)/「文の並べ替え」「空欄補充」はWEBテスティング専用(ペーパーでは出ない)と確認しています。つまり現状は本番では出るはずのない形式が混ざって出題される状態です。

是正案:単元ごとに実施方式タグを正しく付与し、出題ブループリントを方式別に分離する(サンプラ側は methods を読める構造になっているので、データ側の是正が主)。

HIGH4-6. 在庫の偏り — 95単元中55単元が在庫ゼロ、言語は全体の1割

factSPI適用95単元のうち、完全一致・関連ともに在庫0が55単元(完全一致だけで見れば78単元が0)。実際に問題を持っているのは17単元に集中しています。とくに公務員試験で実績337回・ほぼ毎年出る計量図形が0問、資料解釈の実数228回・判断推理の対応186回なども0問です。言語は772問=全体の10.2%にとどまり、言語には難易度4・5が1問もありません

是正案:単元マトリクスの「頻度×在庫」から生成計画を機械算出済み(言語レーン2週・非言語レーン37週の補充計画v1.1)。優先は計量図形・資料解釈・判断推理の空間/対応系と、言語の上位難度。

HIGH4-7. 出題の見た目が単調(テンプレート量産の副作用)

fact「文の並べ替え」200問は100%が同一の足場テンプレート(「〜について、まず現状を確認した→その結果→そこで→その後→以上から」)で、本番SPIの長文分割型とは乖離しています。フロント側の公務員現代文20問も同一雛形の本文使い回しです。

是正案:補充計画の言語レーンでテンプレートを刷新・置換。生成器側に「同一足場の連続生成を弾く」多様性ゲートを追加。

HIGH4-8. 体験模試は答えと解説をクライアントに全部渡している

✅ 解決済み(2026-07-25・Phase C)体験模試(C)・LINE内受験(D)のバンドル同梱を全廃し、出題worker(A)からの都度取得へ切替。答え・解説はブラウザへ配らず、採点はサーバ側(qb-scorer)に一本化しました。出題セット応答に答え・解説が含まれないことを本番実測で確認済み。これで(C)(D)の公開面にもAPI側と同じIP境界が引かれました。以下は切替前の記録です。

fact公開中の体験模試は、6,536問を正答インデックスと解説ステップ込みでJSバンドルに同梱して配布しています(展開16.4MB/gzip転送1.6MB)。API側では「答えは壁の裏、配信と採点だけをAPIで出す」というIP境界を、バケット分離とレスポンスフィルタで厳格に守っているのに、自社の公開面ではその境界が存在しません

※これは「無料体験の問題文は公開物」という割り切りとしては一応筋が通りますが、境界の設計が経路ごとにバラバラであること自体がリスクです。あわせて初回ロード16.4MBはモバイル体験としても重い。

✅ 2026-07-23 の対応(一部)出題worker側にあったより深刻な露出は塞ぎました。当初 mode=taiken は無認証のまま答えと解説を返しており、URLにパラメータを1つ足すだけで1リクエスト100問を答えつきで収集できる状態でした。公開workerから答えバケットのバインディングを物理削除し(アプリ層のフィルタだけに依存しない構成)、本番で全モードの非露出を実測確認しています。
体験模試のバンドル同梱は未解決で、配信の一本化(サーバから都度取得)で解消します。
是正案:§4-2の配信切替(worker経由=答え非同梱)で構造的に解消。少なくとも「無料体験は同梱/会員向け本番は非同梱」の線を明示的に引く。

MEDIUM4-9. 性格検査:出典表記なし・信頼性未検証・規範集団なし・免責が結果画面のみ(詳細は§2-2)

fact①項目45問は書き下ろしの自作で、成果物側に出典表記が無い(設計調査は残っているがコードから参照されていない)。②信頼性係数の検証コードはリポジトリ全体で0件、構想メモのみで未着手。③偏差値は受験者集団ではなく理論的中点(平均3・SD1のハードコード)との比較で、設計意図(受検者集団で正規化)と実装が乖離。4側面への重み係数とライスケール閾値20は根拠の記録が無い裁量値。④保証を否定する免責文は結果画面にしか出ない(受験前・受験中は操作説明のみ)。

是正案:(1) 受験前画面にも免責を出す(最小・即時可能)。(2) 実受験データから因子別の平均・SDを算出して定数を置換=規範集団つき偏差値へ移行(式・UI変更不要)。(3) n≧200 の段階でα係数・項目全体相関・因子構造を検証。(4) 項目データに出典メタデータ欄を追加し、書き下ろしである旨を明記して系譜を残す。

MEDIUM4-10. SCOA体験模試は公開前ブロッカーが4件残って止まっている

fact外部監査2社(sol/Gemini)を通し、solは「現状のまま一般公開は不可」(条件付きGO)。公開前必須のHigh4件は次のとおり。①SVGサニタイザが名前付き実体参照(( 等)を未デコードで通す(現バンクは自社決定論生成のため実害は「悪性SVGが混入した場合」に限定)/②プレビュー公開ゲートがクライアントJS同梱トークンで実質ゲートになっておらず、sitemapにプレビューURLが載る③量産CLIが検品不合格でも公開用バンクを書き出して正常終了する(fail-closedでない)/④知識系34問が内容監査をスキップしたまま「監査済み」の由来情報を付与される

是正案:4件を是正して再監査 → PR → 本番。現状は未デプロイ=実露出ゼロなので、リリース判断を急がなければリスクは顕在化しません。

LOW4-12. LPの記載と実体の乖離

fact公開LPは「合計4,000問超」と表記していますが、実体は正本7,537問/同梱6,536問。また「算術10トピック・推論7型」と記載していますが、実際には非言語18トピック・推論10型です。実力を過小に伝えている方向の乖離です。

是正案:リリースのmanifest件数からLP表記を自動生成する(数字を手書きしない)。

LOW4-13. IRT較正は未着手

unknown設問単位の応答データ(正誤・所要時間)を蓄積する仕組みは動いていますが、IRT較正(項目反応理論による難易度・識別力の推定)を実装したコードは今回の調査範囲では確認できませんでした。現在の難易度1〜5は生成時の設計値であり、実データによる較正値ではありません。

是正案:§4-1のID問題を先に解決しないと較正データが作れないため、順序としては 4-1 → 較正。

HIGH4-14. LINE内受験(LIFF版)のバンクがさらに1世代古い

✅ 解決済み(2026-07-25・Phase C)LIFF版の同梱バンクを全廃し、Web版と同じ出題worker(A)経由の配信へ一本化しました(SPAバンドルに問題ID同梱ゼロを本番実測)。経路による世代・内容の差は解消されています。以下は切替前の記録です。

factLIFF版に同梱しているバンクは5,343問・最終更新 2026-06-22で、Web版(6,536問・7月3日更新)よりさらに古い断面です。1ヶ月以上同期されていません。内訳も語彙501・文章理解50と薄く、非言語3,550に偏っています。

影響:LINE経由で受験した方だけ、より偏った・より古い出題を受け続けます。同じ「Educareの模試」なのに経路によって中身が違う状態です。

是正案:§4-2の配信切替に含めて一本化する。切替までの暫定は最新バンクの再同梱。

HIGH4-15. 重み駆動の出題が「配線済みだが未通電」

fact試験種ごとの単元重みは最新リリース(qb-r1-20260723)に焼き込み済みで、それを使って出題する新サンプラも実装・テスト完了していますが、まだ本番へデプロイしていません(デプロイ経路の再整備が先行条件)。現在配信中のworkerは新フィールドを剥がして返すため、実際の出題は従来どおりの配分です。

影響:「出題実績データで在庫と配分を機械制御する」という設計の本丸が、まだ受験体験に届いていません。

是正案:デプロイ経路の再整備 → サンプラをデプロイ → 出題分布を実測して検収。

MEDIUM4-16. APIバンクに文章理解が含まれていない

fact本日の実測どおり、API経由で配信できるのは7,505問で、文章理解32問は0件です。API側の問題テーブルが長文本文を保持する構造を持たないため、投入時に除外されています。正本リリース側では長文を content-addressed で分離管理できているので、データ側ではなくAPI側の実装が追いついていない形です。

是正案:APIを正本リリース直読み(出題workerと同じ方式)に寄せる。そうすれば長文も自然に扱えます。

MEDIUM4-17. 公務員模試に専用バンクも試験種別の出し分けも無い

fact公務員模試はSPIバンクを分野タグでフィルタして代用しており、試験種タグが付いた問題は6,536問中134問のみ。地方上級・警察・消防・国家一般・特別区・市役所それぞれ50〜72問しかありません。残りは試験種を問わない汎用出題です。

是正案:試験種別ブループリント(重み表は既に整備済み)を出題側に接続し、試験種タグを在庫側にも付与していく。

MEDIUM4-18. 英語(ENG)と SCOA言語尺度が未対応

factSPIの英語(ENG)検査、およびSCOAの言語・英語尺度は問題型の開発自体が未着手です。社内の商品計画書でも「英語対策=真の穴」と明記しています。

是正案:需要(英語を課す自治体・企業の比率)を確認したうえで優先度を決める。現状は非言語・言語(国語)に集中投資しています。

MEDIUM4-19. 単元台帳の未整備領域(人文・社会・時事/2019年以降/データの性質)

fact①人文科学・社会科学・時事は単元taxonomyが未構築で、周期・在庫分析の対象外です(時事は「周期」ではなく「鮮度」で管理すべきという性質の違いもあり別建て設計が必要)。②数的処理の出題実績インデックスは2018年までで止まっており、2019〜2025年の補完が残っています。③そもそもこの実績データは本試験の悉皆リストではなく、市販模試が参照した過去問の実績であり、強いプロキシではあるが上限のある推定値です。

是正案:①人事院など一次ソースからの2019〜2025補完を先に実施(周期の精度が直近ほど効くため)。②人文・社会は講義資料からのtaxonomy新設。③悉皆性の限界は資料に恒久注記として明示し続ける。

CRITICAL4-20. 外販APIの採点エンドポイントが正答抽出オラクルになっている(v1.3 追記)

fact本番で実証しました。ステートレス採点 POST /v1/scores に、同じ問題を選択肢0〜4で並べて1回投げるだけで正答が返りますson-eki-0001 → 応答から正答3が確定・正本の答えと一致)。同一問題の重複送信を禁止しておらず、送信件数の上限もセッション所有の確認もありません。

影響:認証キーを持つテナントが7,537問の答えを機械的に全部抜けます。1リクエストで1問確定するため、後述4-21(レート制限が機能していない)と組み合わさると実質無制限です。外販商材としての価値を失う経路です。

これは今回の改修で入ったものではなく従来からある穴ですが、外販開始と同時に顕在化します。

是正案:SPIドメインのステートレス採点を廃止し、採点をセッション経由(出題→解答→採点)に一本化する。残す場合は同一問題の重複拒否・件数上限・レート制限の実効化を同時に入れる。是正するまで外販は開始しません。

HIGH4-21. レート制限が実際にはリクエストを数えていない(v1.3 追記)

factテナントごとに120リクエスト/分の制限を持つ設計ですが、実装は「直近1分のイベント数」を数えており、通常のAPIリクエストではイベントが追加されません。したがってイベントが120件に満たないテナントは、セッション作成も問題取得も採点も何回呼んでも制限に到達しません。テストも「既に999件ある」状態のモックだけで、リクエストによる増加を検証していませんでした。

是正案:リクエスト単位で確実に加算されるカウンタへ変更し、「N回呼んだらN+1回目が429」という形でテストを固定する。

HIGH4-22. 回答確定後の一時障害で受験ログが永久欠損する(v1.3 追記)

fact解答の記録が成功した直後にイベント書き込みが失敗すると、APIは500を返します。クライアントが再試行しても「回答済み」の分岐で早期に返るため、イベントは二度と生成されません。結果として回答自体は確定しているのに、版情報つきの証跡だけが永久に欠ける状態になります。受験の完了処理にも同じ構造があります。

これは本資料が最重要課題としている「どの世代の問題への回答か特定できない」問題(§4-1)を、これから防ごうとしている当の仕組みに空いていた穴です。

是正案:「回答は記録されたがイベント未記録」の状態を記録し、再試行時に冪等に補完できるようにする。

MEDIUM4-23. 外販APIのロールバック先が互換ではない(v1.3 追記)

fact改修後の外販APIは正本リリースから出題してセッションに固定しますが、ロールバック先の旧版は別系統のコピーから取得・採点します。改修後にセッションを作った後で旧版へ戻すと、旧版に存在しない問題は404になり、世代衝突があれば別問題として採点されます。「戻せる」つもりの手段が、実は戻せません。

是正案:ロールバック時に進行中セッションを終了させる手順を用意するか、「投入後は前進修正のみ」と明示してカナリア投入を条件にする。いずれにせよ runbook として明文化する。

5. キヨさんと握りたい判断

論点現状お伺いしたいこと
① 版のピン留めリリースは版ごと不変・current.json で切替。テナント別に別の版を指すことも追加コストゼロで可能キヨさん側は「常に最新版」でよいか、それとも特定版に固定したいか。§4-1(ID再利用)を踏まえると、外部提供では版固定を推奨します
② 較正データの合流テナント行の calibration_optin は現在 OFFそちらの受験データを当社の較正母集団に合流させるか。合流するならデータ所有・保持期間・越境の扱いを先に定義したい
③ 利用形態REST+OpenAPIで提供中。ブラウザ直叩きはCORS許可ドメイン登録が必要サーバ間連携かブラウザ直叩きか。後者ならドメインをご指定ください
④ 性格検査の提供可否APIのセッションは現状 domain=spi のみ。性格検査はフロント実装+ステートレス採点は domain=personality 対応済み性格検査もAPI提供対象に含めるか。含めるならセッション方式への拡張が必要。§2-2 のとおり規範集団なし・信頼性未検証・出典表記なしという状態なので、外部提供する場合は先に「規範集団つき偏差値への移行」と「免責の前置き表示」を済ませたいと考えています
⑤ 是正の優先順位§4-1〜4-3が最優先という当社評価外部提供の観点から見て、この優先順位でよいか。ご意見をいただきたい

6. 検証エビデンス(再現手順)

本資料の数値は、以下の一次確認で裏どりしています。推定は inference、確認できなかったものは unknown と明記しました。

# 1. API・出題workerの本番稼働確認(本日実測)
curl -s https://educare-cbt-ingest.komuin-sukima.workers.dev/healthz
  → {"status":"ok","time":"2026-07-23T00:49:30Z"}
curl -s https://educare-cbt-ingest.komuin-sukima.workers.dev/openapi.json
  → OpenAPI 3.1.0 / title="SPI Platform API" / 14パス・17スキーマ
curl -s https://spi-questions.komuin-sukima.workers.dev/api/spi/pool/stats
  → {"total":7537, "by_topic_subpattern":[...]}

# 2. 正本バンクの内訳(ローカル正本JSONを直接集計)
spi_bank_build/spi-questions.full.v2.json → 7,537問/非言語6,765・言語772
  トピック25・サブパターン80・全問5択・解説欠落0・平均5.0ステップ

# 3. 正答位置の偏り(正本・トピック別)
  文章理解のみ 32問中27問が index 0(84%)/他トピックは全て20%前後で一様

# 4. 公開面の実バンク(本番配信中のJSバンドルを取得して解析)
curl https://educarelog.net/_astro/ExamStartGate.*.js
  → 6,536問を JSON.parse で同梱(answer・explanation_steps 込み)
  → gzip転送 1.60MB/展開 16.4MB
  → 問題文先頭60字ユニーク 4,581件=重複1,955問

# 5. ID衝突の実証(公開面バンク × 正本の突合)
  共通ID 3,408件 → stem または answer が不一致 3,407件
  例)son-eki-0001 が両者で全く別の問題

# 6. 性格検査(本番配信中バンドルから項目データを直接抽出)
  45項目/開放性8・誠実性10・外向性8・協調性10・情緒安定性9
  逆転12・ライスケール5/5件法/aspect=行動的12・意欲的8・情緒的12・社会関係的13

# 7. APIバンクの断面(キヨさんのテナントキーで実弾)
GET /v1/questions?limit=1        → pagination.total = 7505
GET /v1/questions?topic=文章理解   → total = 0(長文はAPI側テーブル非対応のため除外)
GET /v1/questions?topic=二語の関係 → total = 96(正本と一致)
GET /v1/questions/son-eki-0001    → 問題文がローカル正本と完全一致
  返却フィールド: id/field/topic/difficulty/methods/stem/choices/source
  (answer・explanation_steps は含まれない=答え非露出を実測)

# 8. 性格検査の採点仕様(本番配信中バンドルのコードから抽出)
  定数: 理論平均=3 / 理論SD=1 / ライスケール閾値=20(いずれもハードコード)
  偏差値 = clamp(50 + 10*((因子平均 - 3)/1), 20, 80)  ※受験者集団の統計を参照しない
  4側面 = 因子偏差値の重み付き平均
    行動的{外向性.45,誠実性.35,開放性.2} 意欲的{誠実性.45,外向性.3,開放性.25}
    情緒的{情緒安定性1.0}                社会関係的{協調性.7,外向性.3}
  免責(結果画面のみ): 「ビッグファイブ理論に基づく練習用の自己申告プロフィールです。
                        採用結果や本番の判定を保証するものではありません。」
  リポジトリ全体grep: cronbach|α係数|信頼性係数|因子分析 → 一致0件

# 9. SCOA・LIFF(ローカル正本ファイルを集計)
scoa-questions.bank.json  → 145問(論理75/数理36/常識34・全問5択)
LIFF apps/liff .../spi-questions.bank.json → 5,343問(最終更新 2026-06-22)

7. 2026-07-23 の改修で解決したもの

✅ 本日の改修で解決した項目の一覧 本資料の初版を出した後、同日中に改修を進めました。本番デプロイまで完了した項目と、実装は済んだがデプロイ待ちの項目を分けて記載しています。
項目状態内容
出題workerの無認証での答え露出✅ 本番反映済み公開workerから答えバケットのバインディングを物理削除。全モードで answerexplanation_steps が返らないことを本番実測で確認(version 0eb60a71・13:12反映)
§4-1 問題IDの世代衝突✅ 台帳側は完了UUIDv7の恒久ID(item_family_iditem_version_id)と系譜台帳を新設し、正本7,537問すべてに付与。過去の応答ログ1,428行のうち88.1%を遡及救済(残り170行は世代間で内容が変わっており憶測で割り当てていない)。今後のログに版情報を刻む配線はデプロイ待ち
§4-3 文章理解の正答位置リーク✅ 正本は是正済み新リリース qb-r1-20260723r2 が本番稼働。最大シェア28%へ一様化。再発防止ゲート2本を追加。公開面のバンドルは未反映
§4-11 本番コードがメインライン未統合⚠️ 半分解決本番稼働中のコミットが origin に存在しなかった状態を解消(push済み)。ブランチのメインラインへのマージは未実施
デプロイ正路の不在
(初版では未記載)
✅ 解決出題worker・外販APIともデプロイゲートに未登録で、事故時に戻す手段が存在しませんでした。両者を登録し本番の現状を台帳に記録。実際に1回通して昇格・検証まで成功
判定ゲートも整備しました。外販開始の可否を機械判定する検査を10項目つくり、現在 6項目が緑です。残る4項目は外販API側の改修待ちで、この4項目が緑になるまで外販は開始しません

以下は本資料の初版で課題として挙げ、同日中に対応した項目です。経緯の記録として残します。

CRITICAL4-1. 問題IDが世代をまたいで再利用され、同じIDが別問題を指している → 台帳側は解決済み・配線はデプロイ待ち

✅ 2026-07-23 の対応根本原因を実データで確定しました(両バンクとも各プレフィックスが1からの連番で番号帯が完全に重なる=世代ごとの振り直し)。UUIDv7の恒久IDと系譜台帳を新設し、正本7,537問すべてに付与。過去の応答ログ1,428行のうち88.1%を遡及救済(セッション単位で世代を特定531行/時刻で特定628行/全世代で内容不変99行)。残る170行は世代間で実際に内容が変わっており、憶測での割り当てはしていません。
今後のログに版情報を刻む配線は外販API側の改修待ちです。

fact本番配信中の体験模試バンク(6,536問)とサーバ正本リリース(7,537問)でIDを突き合わせたところ、共通ID 3,408件のうち 3,407件で問題文または正答が一致しません。例:ID son-eki-0001 は、フロントでは「2400円で仕入れ20%の利益を見込み…」、正本では「定価2100円をまず20%引き…」と全く別の問題

影響:設問単位で蓄積している応答ログ(item_responses.item_id)がどの世代の問題への回答か特定できません。正答率・難易度較正・IRT較正といったデータ資産の土台が崩れます。キヨさんが叩くAPI経路そのものは正本と同世代なので現時点で実害は出ていませんが、当社が版を更新した際に「同じIDで違う問題が返る」事故が起きうる構造です。

是正案:①ID体系を「内容ハッシュ or 世代込みID」に変更し、生成器側でID再利用を禁止するゲートを追加。②既存ログには bank_release_id を必須で紐付ける(リリース側にはすでに bank_release_id を全問へ焼き込み済みなので、配信・記録側を合わせれば解消可能)。③移行期は旧IDを別名前空間に隔離。

CRITICAL4-3. 文章理解に正答位置のリークがある(84%が選択肢1番目)→ 正本は是正済み・公開面は未反映

✅ 本日中に正本側は是正されました(ただし公開面は未反映) fact並行作業で修正が入り、新リリース qb-r1-20260723r2 が本番の current.json に切り替わっています。本番R2から答えシャードを直接取得して確認したところ、文章理解32問の正答位置は 0:7/1:6/2:7/3:9/4:3(最大28%) と一様化されていました。あわせてリリースビルドに恒久ゲート2本(トピック単位の正答位置一様性・最大40%/トピック内の重複問題文の遮断)が追加されています。
一方、公開中の体験模試のバンドルは 2026-07-17 のまま変わっておらず、ユーザーが実際に受ける文章理解30問の偏り(57%が1番目)は残ったままです。「正本を直しても公開面が直らない」という §4-2 の構造問題が、そのまま実例として現れた形です。

以下は是正前(本日午前)の実測記録です。fact正本の文章理解32問のうち27問(84%)の正答が選択肢index 0(=一番上)。他の全トピックは正答位置がきれいに一様(各20%前後)なので、文章理解だけの偏りです。クライアント側に選択肢シャッフルの実装が無く並び順のまま表示されるため、受験者から見て「一番上を選べば当たる」状態です。フロント同梱バンク側も、SPI文章理解30問の57%が1番目、公務員文章理解351問は3番目に43%集中(5番目はわずか3%)という偏りがあります。

影響:模試としての妥当性が壊れます。正答率・偏差値も過大評価になります。

是正案:①該当バッチの選択肢を再シャッフルし正答indexを更新して新リリースを焼き直す。②生成パイプラインに正答位置の一様性ゲート(トピック単位のカイ二乗検査)を恒久追加し、偏りが出たリリースはビルドを止める。③配信側にもシャッフルを実装して二重で守る。

MEDIUM4-11. 本番コードがメインラインに統合されていない(feature branch運用)

factSPI Platform API(feat/spi-api-platform-phase1)も出題worker(feat/spi-infinite-serving)も、リポジトリの developmain未マージのまま本番へデプロイされています。

⚠️ 初版より深刻でした(v1.3)調査の結果、出題workerは本番で稼働しているコミット自体が origin に存在しませんでした(ローカルにしか無い状態)。ローカルが失われれば本番のソースが復元できません。本日 push して解消しています。メインラインへのマージは未実施です。

影響:本番で動いているコードがどのコミットか、リポジトリの正史から辿れません。並行開発時の先祖返り事故(過去に実例あり)の温床です。

是正案:本番稼働中の2ブランチをメインラインへマージし、以後はデプロイゲート経由に統一する。
📐 データ契約(Data Contract)— 選択肢・正答・送信値の基準

本仕様書が定義するAPI・バンクに共通する契約です。「選択肢を何番目として数えるか」「正答値の基準」「送信する回答値の意味」「宣言の在り処」を、実装側の解釈違いを防ぐために明文化します(2026-07-31 確定・ANSWER_BASE_MIGRATION_PLAN_20260730.md §10-8)。

ID項目定義
DC-1選択肢の数え方選択肢配列は先頭を0とする配列添字で数えます。choices[0] が1番目の選択肢です。画面表示の「選択肢1」は添字0の投影(表示専用の変換)です。
DC-2正答の基準バンク内部の answer1基準へ切替済みです(2026-08-01 完了)。切替は当社内部の是正であり、本仕様のAPI挙動・採点結果は切替前後で同一であることを機械検査(全問題×全choice点の突合)で保証済みです。
DC-3解答送信の意味choice当APIが返した choices 配列の位置(0始まりの配列添字)です(2026-07-31 確定)。-1 は「未回答」を表す正規のセンチネル値です。
DC-4宣言の在り処正答を含むデータは manifest トップレベルの answer_base 宣言と同伴でのみ解釈します。宣言の無いデータは読みません(fail-closed・既定値で補いません)。

※ この節は共有済みの4仕様書(SPI/公務員/SCOA/適性)すべてに同一内容で追記しています。