1. ひとことで
Student 2 は、学生が「今やりたいこと・空き時間・場所」を登録すると、 説明可能なルールベーススコアで相性のよいグループを組み、 条件を満たすときだけ Micro Event を生成し、根拠を AI ログに残す担当です。 ML / LLM / SNN は使いません。
2. システム全体図(ブロック)
HALO 全体の中で、Student 2 が所有する箱と、他担当との境界です。
flowchart TB
subgraph FE["フロントエンド"]
ST["/app/status
What Now UI"]
end
subgraph S2["Student 2(本ドキュメントの範囲)"]
API1["POST/GET /student/status"]
API2["POST /ai/micro-events/generate"]
API3["GET /ai/micro-events/candidates"]
ORCH["MicroEventOrchestration"]
MATCH["matching_service
純粋ロジック"]
GEN["micro_event_generator"]
STORE["StatusStore + AiEventLogStore"]
end
subgraph EXT["他担当 / 外部(契約待ち)"]
S1["Student 1
Event Core"]
S3["Student 3
Beacon / Check-in"]
S4["Student 4
Friends / UX"]
end
DB[(PostgreSQL)]
FAKE[["Fake EventCreator
Fake BeaconCatalog"]]
ST --> API1
ST --> API2
API1 --> STORE
API2 --> ORCH
ORCH --> MATCH
ORCH --> GEN
MATCH --> FAKE
GEN --> FAKE
STORE --> DB
API3 --> DB
FAKE -. 契約後に差替 .-> S1
FAKE -. 契約後に差替 .-> S3
GEN -. 候補は自動Joinしない .-> S1
S4 -. Home / My Events 表示 .-> S1
図 1 — Student 2 の箱と他モジュール境界。実線は現行、点線は契約後の接続。
3. 完了範囲チェック
| フェーズ | 内容 | 状態 |
|---|---|---|
| 0 | 仕様読解・設計判断 | 完了 |
| 1 | 環境・Compose・seed 基準確認 | 完了 |
| 2 | What Now 状態の保存・取得 | 完了 |
| 3 | 説明可能なマッチング | 完了 |
| 4 | Micro Event 自動生成 + AI ログ | 完了 |
| 5 | 生成/候補 API・What Now 最小接続 | 完了 |
| 6 | 評価指標・不足試験・デモ手順 | 完了 |
必須 API(仕様どおり実装済み)
POST /student/status— What Now 登録(旧行は同一 TX で即時失効)GET /student/status/me— 自分の有効ステータス取得POST /ai/micro-events/generate— マッチング→生成の手動トリガGET /ai/micro-events/candidates— 評価ロール向け AI ログ閲覧
4. エンドツーエンド・データフロー
生成ボタンを押したあとの一本化された処理です(フェーズ 5 オーケストレーション)。
flowchart LR A["有効な
student_current_status"] --> B["MatchingCandidate
へ変換"] B --> C["除外ゲート"] C --> D["ペア採点"] D --> E["貪欲グループ形成
2〜5人"] E --> F["カテゴリ・時間・場所・manager 決定"] F --> G{"生成条件 OK?"} G -->|Yes| H["EventCreator.create
(現状 Fake)"] G -->|No| I["skipped / failed"] H --> J["ai_event_logs
created"] I --> K["ai_event_logs
skipped/failed"] J --> L["DB commit
(ログ)"] K --> L
図 2 — Generate 実行時の主データフロー。
sequenceDiagram
participant UI as /app/status
participant API as FastAPI
participant Orch as Orchestration
participant Match as matching_service
participant Gen as micro_event_generator
participant Log as AiEventLogStore
participant Fake as Fake EventCreator
UI->>API: POST /student/status
API->>API: 旧 status 失効 + 新行 INSERT
UI->>API: POST /ai/micro-events/generate
API->>Orch: run()
Orch->>Orch: list_active_statuses
Orch->>Fake: ACTIVE 候補集合
Orch->>Match: run_matching(+ duplicate sets)
Match-->>Orch: groups / exclusions
Orch->>Gen: run_micro_event_generation
Gen->>Fake: create MICRO event
Gen->>Log: flush created/skipped/failed
Orch->>Orch: commit (AI logs)
API-->>UI: data = 作成イベント配列 or null
図 3 — 画面操作からレスポンスまでのシーケンス。
5. What Now(状態保存)
学生の「今」を短命な行として保存します。送信のたびに新行を INSERT し、
同じ学生の有効な旧行は同一トランザクションで expires_at = now() にして即時失効させます。
flowchart TB IN["入力
intents / periods / custom time
location / note_to_ai"] --> VAL["検証
intent≥1, 終了時刻, Beacon ACTIVE"] VAL --> NORM["空き時間の正規化・結合
Asia/Tokyo → UTC"] NORM --> EXP["expires_at 決定
最終空き終了 or 当日末"] EXP --> TX["同一 TX"] TX --> OLD["旧有効行を now で失効"] TX --> NEW["新行 INSERT"] NEW --> OUT["GET /status/me
expires_at > now の最新1件"]
図 4 — What Now 保存ブロック図。
| 項目 | ルール(実装済み) |
|---|---|
| 有効判定 | expires_at > now()。同一学生は created_at 最新の1件 |
| 時限 | 仮時限表(1st〜6th)。登録日の Asia/Tokyo として解釈 |
| 自由入力 | HH:MM-HH:MM の custom_available_time |
| 空きなし | 保存は可。マッチングでは NO_AVAILABILITY 除外 |
| 認証(暫定) | X-Student-Id(未指定時 user_001)。未知 ID は POST で 401 |
6. 説明可能なマッチング
matching_service.py は DB/HTTP/Event 生成に依存しない純粋ロジックです。
「なぜそのスコアか」を score_detail に残します。
除外ゲート → 採点 → グループ
flowchart TD
CAND["候補スナップショット"] --> G1{"status 有効?
空き時間あり?"}
G1 -->|No| X1["除外ログ"]
G1 -->|Yes| G2{"準備15分後に
共通30分以上?"}
G2 -->|No| X2["除外"]
G2 -->|Yes| G3{"適合 Beacon あり?
定員・並行OK?"}
G3 -->|No| X3["除外"]
G3 -->|Yes| G4{"重複 ACTIVE
候補集合でない?"}
G4 -->|No| X4["除外"]
G4 -->|Yes| PAIR["全ペアを加重採点"]
PAIR --> TH1{"ペア ≥ 0.60?"}
TH1 -->|No| DROP["辺を捨てる"]
TH1 -->|Yes| GRP["貪欲グループ 2〜5人
selection_score 順"]
GRP --> TH2{"グループ matching_score ≥ 0.70?"}
TH2 -->|No| DROP2["不採用"]
TH2 -->|Yes| OUT["MatchedGroup + score_detail"]
図 5 — マッチングのゲートと閾値。
スコア要因(重み合計 1.00)
- グループの公開点は要因の加重和(ペア平均 + グループ共通時間・選定 Beacon)。
selection_score = matching_score + size_bonus(2人=0、+1人ごと +0.02、最大 +0.06)。- 同一実行内で学生を再利用しない。同点は安定した ID 順でタイブレーク。
- 現状
InterestSourceは常に unknown → interest 一致は 0.50 固定。
7. Micro Event 生成
マッチングで得たグループごとに、カテゴリ・開催時間・manager・場所を決め、 条件 NG ならスキップ、OK なら Event を作ります。候補学生は自動 Join しません。
flowchart TB
G["MatchedGroup"] --> INT{"共有 intent → カテゴリ?"}
INT -->|なし| S1["skip: no_shared_event_intent"]
INT -->|あり| CAT["優先順で1カテゴリ
study → language_exchange → wellness → lunch → social"]
CAT --> TIME["開始 = now+15分
長さ = 30/45/60分"]
TIME --> MGR["manager 選定
can_facilitate 優先"]
MGR --> PLACE["Beacon 採点
近接0.70 + 定員0.30"]
PLACE --> DUP{"generation_key
重複 ACTIVE?"}
DUP -->|Yes| S2["skip: duplicate"]
DUP -->|No| CR["create MICRO / AI / ACTIVE
approval_required=false"]
CR --> LOG["ai_event_logs + score_detail"]
S1 --> LOG2["ai_event_logs skipped"]
S2 --> LOG2
図 6 — 生成パイプライン。
| 項目 | 実装内容 |
|---|---|
| イベント属性 | event_type=MICRO, created_by_type=AI, status=ACTIVE, approval_required=false |
| 開催時間 | 残り共通 30–44→30分、45–59→45分、60+→60分 |
| 重複防止 | 順序なし候補集合 + カテゴリの決定論的 generation_key |
| note_to_ai | 制御キーワードのみ抽出。生テキストはログに残さない |
| レスポンス | 作成イベントの配列。0件時は data: null |
8. Port / Adapter 境界
マッチング本体は共有 DB/API を直接呼ばず、Port 経由で事実を受け取ります。 差し替え可能な境界として設計済みです。
flowchart LR CORE["純粋コア
availability / matching / generator"] CORE --- P1["StatusStore"] CORE --- P2["BeaconCatalog"] CORE --- P3["ProfileReader"] CORE --- P4["InterestSource"] CORE --- P5["EventCreator"] CORE --- P6["AiEventLogStore"] CORE --- P7["IdCodec"] P1 --> R1["SQLAlchemy 本実装"] P2 --> F2["Fixture / Fake"] P3 --> F3["Fixture"] P4 --> F4["AlwaysUnknown"] P5 --> F5["Process Fake"] P6 --> R6["SQLAlchemy flush"] P7 --> F7["no-op"]
図 7 — Port と現行 Adapter。緑系=本実装、茶系=Fake。
| Port | 状態 | 意味 |
|---|---|---|
| StatusStore | 本実装 | PostgreSQL student_current_status |
| AiEventLogStore | 本実装 | flush のみ。commit はオーケストレーション |
| EventCreator | Fake | プロセス内メモリ。実 Event 行と未接続 |
| BeaconCatalog | Fixture | Student 3 契約後に差替 |
| ProfileReader | Fixture | 学科・友人・can_facilitate |
| InterestSource | AlwaysUnknown | interest スコア 0.50 固定 |
| IdCodec | no-op | UUID 決定後に変換層へ |
9. API と画面の接続
flowchart TB
subgraph StudentUI["学生 UI"]
A["/app/status"]
end
subgraph Eval["評価・管理"]
B["candidates API
X-Student-Id: user_eval_admin"]
end
subgraph Endpoints["Student 2 エンドポイント"]
E1["POST /student/status"]
E2["GET /student/status/me"]
E3["POST /ai/micro-events/generate"]
E4["GET /ai/micro-events/candidates"]
end
A --> E1
A --> E2
A --> E3
B --> E4
図 8 — 画面と API の配線(フェーズ 5 の最小接続)。
reset_process_fake_event_creator() または docker compose restart backend が必要です。
10. データの流れ(保存物)
flowchart LR
subgraph Persist["PostgreSQL に永続"]
S["student_current_status"]
L["ai_event_logs"]
end
subgraph Memory["プロセスメモリ(Fake)"]
E["Fake MICRO events"]
D["ACTIVE duplicate sets"]
end
POST1["POST /student/status"] --> S
GEN["generate"] --> E
GEN --> L
E --> D
D --> GEN
CAND["GET /candidates"] --> L
図 9 — 何が DB に残り、何が Fake メモリか。
AI ログに入れる / 入れない
| 含める | 含めない(プライバシー) |
|---|---|
学生 ID・status ID、正規化時間、intent、Beacon ID、共通キーワード、候補 ID、理由コード、設定版/ハッシュ、score_detail |
氏名、メール、住所、note_to_ai 原文 |
11. 評価・テスト
flowchart TB
subgraph Measurable["今測れる"]
M1["created / skipped / failed 件数"]
M2["score_detail の内訳"]
M3["candidates API"]
end
subgraph Later["実 Event 結合後"]
L1["Join rate"]
L2["Check-in rate"]
L3["No-show rate"]
L4["Micro Event success rate"]
end
subgraph Out["初期版では未測定"]
O1["学生満足度スコア"]
end
FN["micro_event_metrics.py
純関数"] --> Later
図 10 — 評価指標の測定可否。
- テスト結果(2026-08-21): 79 passed(unit 63 / API 16)
- 指標の純関数は実装済み。公開集計 API は追加していない
- 満足度は承認済みアンケート設計がないため未測定と明記
12. 未結合・チーム確認待ち
| 事項 | 暫定 | 状態 |
|---|---|---|
| ID 型 | 当面 str | open |
| interest データ源 | 常に不明 → 0.50 | open |
| 正式時限表 | Student 2 仮スロット | open |
| Event / Beacon 契約 | Fake adapter | open |
13. 主要ファイル一覧
コア
backend/app/student2/(config, availability, ports, adapters, status_store, ai_event_log_store, fixtures)
backend/app/services/matching_service.py
backend/app/services/micro_event_generator.py
backend/app/services/micro_event_orchestration.py
backend/app/services/micro_event_metrics.py
backend/app/services/status_service.py
API
backend/app/api/student_status.py
backend/app/api/micro_events.py
画面
frontend/app/app/status/page.tsx
仕様メモ(エンジニア向け正本)
docs/ja/student-2-design-decisions.md
docs/ja/student-2-progress-report.md
この HTML は説明用です。API パス・フィールド名・閾値の契約正本は
docs/api-contract.md と設計決定書を優先してください。