Phase:P3 — Exploration + Roll + AI
本文件只定義 P3 各 Subphase 完成後什麼必須成立。具體 DB schema、API、module、MCP transport、event delivery 與 permission wiring 放在同目錄的開發設計方針.md;自動/人工驗收與 closeout evidence 放在測試指南.md。
最後更新:2026-09-08
P2 已把 Web 的 Room → Campaign → Roster → Seat → Lobby → Session 全鏈路做成可靠的 Server State:Session Start 時會固定本場 DM Controller 與 Player Seat 的 Active Character,支援 Late Join、End、Abandon、Resume,並保證同一 Character 不會同時被兩個 active Session 使用。
P3 是第一個真正把 active Session 變成可跑 Exploration 的桌面 的 Phase。P3 關門後,真人與外部 AI 必須能在同一場 Session 中:
P3 不是 Combat Phase。Quick Combat 留給 P4,Tactical Combat 留給 P5。P3 也不建立 Adventure Definition / Campaign Runtime(P6),不建立完整跨 Session Timeline、Snapshot / Restore、broader Export(P7)。
P3 的產品硬邊界:
P3 固定拆成六個可獨立實作、驗證與 commit 的 Subphases:
P3-A — Session Table Runtime & Event Stream
↓
P3-B — Exploration, Chat & Actions
↓
P3-C — Roll, Check & PendingAction
↓
P3-D — AI Controller, Scoped Token & Handoff
↓
P3-E — AI Tool Surface & Event Delivery
↓
P3-F — Full P3 Integration & Closeout
三份 P3 文件必須使用完全一致的名稱與順序。
不得在 P3-A 順手做 Chat UI;不得在 P3-C 先做 P4 Combat;不得在 P3-E 因 AI DM 需要 context 就提前建立 P6 Adventure Runtime;不得為了 event history 提前做 P7 的完整 Timeline / Snapshot。
P3 不重造以下 P2 能力:
active_character_session_leases 的同角色 active Session 唯一性。live_character_write_scope() / live_draft_write_scope() / unleased_character_write_scope() 系列授權入口。SessionResumeService 的「組合既有 truth,不另建第二份 Session snapshot」原則。P3 新的 GameAction / table write permission 必須擴充既有 active Session scope,而不是另外做一套「AI 權限」或「桌內 Character write」判斷。
但 P2 現行 caller identity 與 Session lifecycle authorization 實際上是 Human-only:既有 Room access session、current-DM 判斷與 live Character write scope 都不能直接代表 AI controller。P3 因此必須把桌內 gameplay caller 收斂成單一 TableActorContext/等價 typed actor context,再由 Human Room access 或 AI controller grant 各自 resolve 進來;不得替 AI 偽造 RoomAccessAuthority,也不得在 MCP tool 旁邊另做一套授權。
這個 migration 的產品不變量是:
P3 若新增 multiplayer capability,route protection 與 /api/meta capability 宣告必須同一 Subphase 同步交付,不能再發生 route 已要求 capability、Web 卻沒宣告而整頁不可達的 P2-F 缺陷。
active Session 在 P3 起除了 P2 的 participant identity,還有一份當前桌面 runtime truth。它必須能在 browser reload、Human reconnect、AI reconnect、server process restart之後重新取得,而不依賴舊 React state、舊 browser memory 或舊 AI conversation memory。
P3 runtime 至少要能恢復:
P3 不把上述資料包成一份會與 canonical tables diverge 的大 JSON snapshot。Resume 仍由 Server 讀取 canonical truth 後組合。
Session End / Abandon 後,P3 已 commit 的 session data 不刪除;它會成為未來 P7 Timeline / export 的來源之一,但 P3 本身不提供跨 Session history browser、全文搜尋、Snapshot / Restore 或 Undo。
建立所有 P3 功能共用的 durable in-session runtime / event substrate,讓 browser 與 AI 都能用同一個 ordered stream 取得「自某個 revision / sequence 之後發生了什麼」,並能在 restart 後繼續。
SessionResumeService 當即時同步方案。after_seq / 等價 cursor 只補缺的 event;cursor 太舊或資料不可用時可以安全 fallback 到完整 current-state resume。把 P2 的 Session page 變成真正可用的 Exploration table:Main Stage 是世界舞台,Chat 是桌上人物與玩家說話,兩者分離;真人不需要先建 Scene / NPC / Quest 才能描述行動。
規格企劃.md 一致。/action、/search、/whisper、/ooc 在 P3-B 轉成同一 typed Exploration input;/check 的正式 ownership 在 P3-C。Slash command不得形成第二套 business endpoint / persistence model。/search 只是一般 Exploration Action 的語意捷徑,不會自動選 Investigation / Perception、不會自動建立 RollRequest;是否需要 Check、用什麼 Skill / DC仍由 current DM裁定。zh-TW / en,並進既有 hardcoded-copy / locale parity gate。current_scene_id、Fog of War、Vision / LOS。建立正式 Roll / Check lifecycle,以及需要等待 roll 或 DM 處理的 PendingAction。正式骰子由 Server authoritative;Secret Check 的秘密由 Server 保護。
public、roller+DM、dm-only;secret DC 與 dm-only result 不送 Player / AI Player。/check 必須在 P3-C 被正式接手:Player 使用 /check只能表達 Check intent / 進入同一 Check UX,不得自行決定 secret DC或繞過 DM 建立正式裁定;current DM則可由同一 command / UX建立合法 RollRequest。pending、processing、waiting_for_roll、resolved、cancelled,且狀態 transition 由 Server 驗證。RoomAccessContext.access_session_id hardcode進新 service。P3-D 接上 AI grant後,AI 走同一 service,不另建 AI state-write path。把 P2 只有 Human / None 的實際 controller 流程擴充成真正可用的 AI controller,建立 revocable、Seat-scoped、Session-scoped 的 AI credential。Player 可 Human ↔ AI 接手;DM 仍遵守整場固定 controller、不做中途 Human ↔ AI 交接。
AI + Offline 是合法狀態。session_id 尚未綁定時,它只能用於取得自己被指派 DM Seat 的最小 pre-session context與 Start Session所需流程;不能讀 active Session private event、Chat/Narration、Roll、Character State或其他 gameplay runtime。completed/archived、Room被刪除或Owner明確revoke時必須失效;成功 Start 後才轉成該 Session 的固定 controller credential並受 Session End/Abandon lifecycle約束。Let AI Control,產生/rotate scoped token,並把同一隻 Active Character 的 controller切到 AI;Character identity、HP、Inventory、Spell、Current State不複製。Let AI Control 可 optional 接收 Temporary Handoff Instruction。它只屬於這次 AI handoff / controller grant,不是 Character Note、Biography、Roleplay Guidance、Campaign Fact或永久 knowledge。Take Back Control、grant revoke、Session End或Abandon後立即失效,下一次 handoff / 下一場 Session不自動沿用。Take Back Control 的 self-service 發起者必須是當初執行 Let AI Control 的同一個仍有效 Human Room access session。 Server必須保存這個 handoff return identity;同 Room 的其他 member、相同 display name、重新登入後產生的新 access session都不能冒充原 handoff Human。Take Back Control 或合法 administrative reassignment完成後舊 AI Token立即失效;舊 token後續 Chat、Roll、Character state write、event wait全部被 Server拒絕。access_session_id 與 AI (grant_id, generation) 都 resolve 成同一 TableActorContext/等價 typed context;Session Start、current-DM 判斷、Late Join、End、current-DM Abandon分支與 live Character write authorization都必須接受合法 Human 或 AI current controller。AI 不建立假的 Room authority,Owner Abandon escape hatch仍保留既有 Human Room authority路徑。controller_kind='ai' 加上所有既有 Human access-session欄位為 NULL 來代表「某個 AI 正在控制」。正式交付外部 AI 可使用的 structured tool surface。P3 至少有一條可由真實 MCP client連線的 production-like入口;tool handler只作 transport adapter,核心規則仍與 Human UI共用。
2026-07-28 的 stateless Streamable HTTP形態為基準,若實作時官方 SDK有更新,只能在不改產品契約的前提下採相容版本。get_pending_events() / wait_for_event(timeout) 或等價 tool 必須建立在 P3-A durable event stream上;timeout / reconnect後以 cursor重取,不依賴 long-lived model conversation或 process memory。wait_for_event timeout是正常結果,不是 error;client可以安全再次呼叫;實際 HTTP wait 必須沿用 P3-A async/no-DB-hold contract,MCP adapter不得重新用同步 blocking wait包一層。execute_sql、patch_raw_state 類 escape hatch。resolve_action() orchestration。 P3 AI DM使用較細粒度 Narration / Request Check / Current State action等共用服務;完整 narration + runtime world write-back + persistent facts orchestration由 P6 接手,完整 Timeline integration由 P7接手。用真 PostgreSQL、真 browser、真 restart、真 external MCP client與完整 permission matrix證明 P3 是可跑 Exploration 的產品,而不是一組各自能通的 endpoint。
/action /check /search /whisper /ooc 都有對應實作與 browser / parser evidence;/search不自動roll,/check不讓Player繞過DM裁定。zh-TW / en,Session頁加入整頁 bilingual crawl / overflow / raw-key gate。resolve_action()或P7 Timeline / Snapshot;文件明列仍然存在的產品邊界與已知限制,包含「P2 Room access session不是跨裝置持久 Human identity」。P3 不做:
resolve_action() orchestration(P6):P3-E 只提供完成 Exploration 所需的細粒度 shared tools;P6 才負責把 narration、runtime world state、persistent facts等一次 resolve / write-back。P7 再把該 transaction完整投影到正式 Timeline。Take Back Control只能可信地驗證原 Let AI Control 的同一 Room access session;若該 access session遺失,改走 Owner/DM administrative Seat reassignment,不用 display name或同 Room member冒充同一人。P3 關門後,Adventure Table 應第一次具備這條完整路徑:
Create / Enter Room
→ Character / Campaign / Lobby
→ Start Session
→ Human / AI 坐上 Seat
→ Exploration Stage + Chat / Action
→ DM可代理Player Seat處理缺席/無回應角色
→ DM Request Check
→ Server authoritative Roll
→ Pending / private event / reconnect
→ Player Human ↔ AI handoff + optional Temporary Instruction
→ Session End / Abandon revoke session AI tokens
此時已能用真人 DM 或外部 AI DM 跑非戰鬥 Exploration;下一個正常產品 Phase 是 P4 — Quick Combat。