P4 — 測試指南
Phase:P4 — Quick Combat
本文件定義 P4-A~P4-F 的自動/人工驗收與 closeout evidence。產品完成條件以 實作規格.md 為準;具體架構、schema、API、MCP與transaction contract以 開發設計方針.md 為準。
最後更新:2026-09-13
1. P4 Subphase 順序
三份 P4 文件固定使用:
P4-A — Monster & Combatant Foundation
P4-B — Combat Lifecycle, Initiative & Action Economy
P4-C — Attack, Damage & Core Action Resolution
P4-D — Spells, Conditions, Concentration & Reactions
P4-E — Quick Combat UI, DM Adjudication & AI Tool Surface
P4-F — Full P4 Integration & Closeout
每個 Subphase的 code與對應 tests同一小階段完成;先focused local驗證與static review,review完成後才依 AGENTS.md gate使用 GitHub Actions。
2. P4 測試核心風險
P4最危險的 regression包括:
- Combat被錯做成 Session-local,End Session就消失或清掉。
- 同一 Campaign併發建立兩場 active Combat。
- retry Attack造成重擲/重傷害/重扣 slot或 action。
- client可直接跳 current turn或重置自己的 Action。
- DM proxy被當成 subject Player自己操作,audit丟失 acting DM。
- DM proxy走 raw edit bypass,不消耗 subject action/resources。
- Player在非自己 Turn執行一般 Action / Bonus Action。
- Reaction只能在自己 Turn用,或 reconnect後 ReactionRequest消失。
- Quick Combat偷偷自算 distance / range / AoE,製造假精準。
- 每次正常 Attack都停給 DM approve,造成不可玩的 click-heavy流程。
- enemy exact HP / AC / recharge / hidden resources從 REST、event、Resume或 MCP任何一條路洩漏 Player。
- UI隱藏 enemy HP但 API payload仍包含。
- Monster Template與 Instance混在一起,打過一次後模板永久少血。
- content pack更新讓進行中的 Monster Instance live stats瞬間改變。
- SRD monster source / count沒有 pin,upstream drift後 content completeness仍假綠。
- zh-TW只靠 English fallback通過,導致首次顯示 Monster stat block時大量漏譯。
- SRD monster資料只顯 description,連常見 attack/save/damage都沒有可機器執行欄位。
- 為少數特殊能力引入 generic DSL並快速失控。
- Combat另建一套 RNG / roll tables,與 P3 formal roll不一致。
- Damage pipeline錯把 modifier也 double於 crit。
- active Combat仍允許 Player用 absolute
current_hp patch繞過 Temp HP、Concentration與0 HP consequences。
- shared Character Current State新增 Concentration / Exhaustion / Death Save等欄位後,Character JSON v1或 Standalone roundtrip遺失資料。
- Temp HP / resistance / immunity順序錯誤。
- 0 HP monster自動 Dead,剝奪 DM outcome裁定。
- Combat End錯清 concentration / persistent condition / inventory / resources。
- Combat End漏清 round/current turn/action/reaction/ready/death-save cleanup。
- Spell從錯誤 spellcasting source計 DC / attack bonus,multiclass / Pact Magic被混成一池。
- 新 concentration沒有結束舊 concentration,或 damage沒有建立 concentration save。
- Condition只是 icon,Rules Engine完全不受影響。
- AI tool直接提供 raw state patch繞過 Combat services。
- ChatGPT Web看得到 tool但 briefing沒有 combat loop,AI停在 host chat。
- P4新增 web schema污染 standalone SQLite。
- PostgreSQL suite因 env沒設而 silent skip。
- E2E跑到舊 server image產生假綠。
P4 minimum gate:
campaign-scoped durable combat
+ one-active-combat concurrency invariant
+ initiative / turn authoritative state
+ action economy validation
+ P3 formal-roll reuse
+ atomic/idempotent attack + damage
+ enemy secrecy at projection layer
+ SRD monster/beast content completeness
+ Quick Enemy lifecycle
+ spell/resource correctness
+ conditions/concentration/reactions
+ no fake Quick geometry
+ DM adjudication path
+ Session-boundary resume
+ Human/AI service parity
+ real PostgreSQL migration/concurrency
+ restart recovery
+ standalone independence
+ real browser Quick Combat
+ real ChatGPT Web combat journey
3. 執行環境與指令原則
沿用 AGENTS.md 與 P3已記錄的 Windows / PowerShell 5.1規則:不使用 &&;backend pytest cwd在 apps/server,interpreter使用 repo root .venv。
Backend focused示意:
Set-Location .\apps\server
..\..\.venv\Scripts\python.exe -m pytest tests\test_p4a_monsters.py -q
Frontend:
Set-Location .\apps\web
npm test -- --run
npm run build
E2E必須使用會 rebuild server + web的既有 full-stack路徑或 P4 wrapper,不得只 rebuild web。
若 P4建立 dedicated PostgreSQL env,建議:
但 workflow仍要同時設定 required legacy test讀取的 env,並以測試輸出證明沒有 skip。
P4-A — Monster & Combatant Foundation
A.1 Content completeness
自動測試必須:
- 以 checked-in manifest鎖定
5e-bits/5e-database@ce47a18dfeb3e41a1b2a2dfe00a25761c3c3a4f1 / src/2014/en/5e-SRD-Monsters.json,assert expected_records == 334 且 materialized Monster record count剛好 334;再 assert expected_beasts == 87 且實際 type == "beast" record count剛好 87。Beast由同一 corpus subset取得,不另算第二份 source。
- 驗證每個 entry可由正式 ContentRegistry載入,stable key唯一,缺一筆/多一筆/duplicate都 fail。
- 驗證必要 core fields存在。
- Locale gate分層驗證:P4-A每隻 Monster的
name 與 Trait / Action / Bonus Action / Reaction / Legendary Action等 named affordance都必須有 en + zh-TW;尚未 user-visible的 long-form desc可暫時只有 canonical English,但不能把 English fallback計為 zh-TW completeness。一旦 P4-A expose desc,A.1即同時要求 desc zh-TW。
- 驗證常見 attack/save/damage/recharge action可 parse成 typed fields。
- 對 partial / dm-adjudication action驗 description保留,不因 importer無法結構化而丟內容。
不要只用 3隻 fixture代表「全 SRD已導入」。
A.2 Template / Instance separation
至少測:
- Goblin Template建立 Instance A/B。
- A扣血、上 condition、消耗 reaction。
- B與 Template完全不變。
- Save A as Template產生新可重用 template時,不帶 current HP / initiative / reaction spent。
A.3 Quick Enemy
測最低 Name / AC / HP / Speed可加入;沒有 attack時仍可存在;加 Club +4, 1d6+2後可被後續 P4-C resolver讀取。
A.4 Enemy secrecy
同一 instance由 DM / Player actor讀:
- DM DTO有 exact HP / AC / hidden resources。
- Player DTO沒有這些 key,而不是 value=null後仍洩漏 schema hint。
- Player可得到公開 condition / wound band。
- 直接猜 instance id也不能取得 full view。
P4-B — Combat Lifecycle, Initiative & Action Economy
B.1 Active Combat concurrency
真 PostgreSQL至少兩個 concurrent Start Quick Combat transaction打同 Campaign:只能一個成功建立 active Combat,另一個拿 stable conflict error;DB最後只有一場 active。
B.2 Initiative
測:
- PC
d20 + DEX。
- Monster initiative。
- monster group initiative。
- advantage/disadvantage若有合法來源。
- tie需要 deterministic / DM adjudication後,resume order不重排。
- mid-combat entrant加入合法 order。
每個正式 initiative可追到 P3 RollResult;不得只有 final total無 raw die/audit。
B.3 Turn / economy
至少覆蓋:
- start round 1 / first turn。
- advance到下一 combatant / round 2。
- Action只能消耗一次。
- Bonus Action只能消耗一次。
- Reaction合法 window可在他人 Turn消耗並於規則 timing恢復。
- Extra Attack attack count bookkeeping。
- Player在非自己 Turn一般 Attack拒絕。
- DM proxy消耗 subject economy而非 DM economy。
- Dash / Disengage不產生 movement feet欄位。
B.4 Session boundary
Journey:
Session A start Combat
→ Round 3某人的 Turn
→ End Session A
→ assert Combat仍active、state不清
→ Start Session B same Campaign
→ Resume exact Round / Current Turn / entries
另外測 Abandon Session對 Combat state的產品規格行為不得誤清資料;若 current Session結束後沒有合法 DM可操作,Combat只是等待下一 Session,不自動 end。
Party差異至少再測:
- Session B仍有同一 Character → 本場 controller取得 existing combat entry authority,不新增 duplicate entry。
- Session B缺少某 Character → entry / initiative保留,任何 Player不可操作;current DM可 skip / withdrawn / removed,或明確 proxy該 Character。
- absent Character沒有 current Seat時 audit仍保留 acting DM + subject Character,不偽造舊 controller。
- Session B / Late Join新 Character → 不自動加入;DM以 mid-combat entrant加入並完成 initiative後才進 order。
P4-C — Attack, Damage & Core Action Resolution
C.1 Attack rules
Table-driven tests至少含:
- normal hit / miss。
- advantage / disadvantage。
- Nat20 crit:double dice only。
- Nat1 auto miss。
- multi-part damage。
- resistance / immunity / vulnerability。
- Temp HP先吸收。
- exact 0 HP / healing from 0。
C.2 Atomicity / duplicate
對同一 command id:
- sequential retry只一個 RollResult / damage event。
- concurrent duplicate只一次 HP change / action consumption。
- 模擬 transaction failure在 event append前/後,不能留下 HP改了但event沒commit或反向狀態。
C.3 DM adjudication boundary
對 ranged attack / AoE等需要 geometry facts的 action:
- 不提供裁定時不得自動猜「在射程內」。
- 產生 pending adjudication後 state可 reload。
- DM決定 in range後沿同一 action繼續,不重新 roll前置骰。
- DM決定 out of range後不扣不該扣的資源/damage。
C.4 Player 自行扣血與 Direct Edit boundary
active Combat至少測:
- Character
HP=20, Temp HP=5,Player UI輸入「受到 7 damage」→ Temp HP=0, HP=18,不是直接把 current_hp減 7。
- damage中的 Character正在 Concentrating → 同一 pipeline建立合法 Concentration save request。
- damage把 PC降到 0 → 同 transaction套用 Unconscious + Prone / death-save state。
- 一般 Player / AI Player嘗試 raw absolute
current_hp patch繞過 pipeline → reject或不可由 Combat gameplay surface取得。
- Human DM Direct Edit absolute HP → 作為 correction commit,不觸發新的 damage consequence,且有 audit event。
- outside active Combat既有 Current State手動 patch仍維持相容。
C.5 Grapple / Shove / Death
覆蓋 opposed checks、constraints、Grappled / Prone outcome與 death-save所有 nat / threshold branch。
Monster到 0 HP時 assert status沒有自動 dead;只有 DM outcome action改變。
P4-D — Spells, Conditions, Concentration & Reactions
D.0 Shared Character State / JSON compatibility
新增 Concentration、Exhaustion level、Death Save、persistent Temporary Effects時至少驗:
- shared Character persistence與
character@head migration,Standalone SQLite同樣有合法 schema;Web-only combat_entries不進 Standalone。
- 既有 locked Character JSON v1 fixture仍可 import,缺新欄位時得到 backward-compatible defaults。
- 新版 Web export → Standalone import → export,以及 Standalone → Web roundtrip,新增 Current State欄位不遺失、不改既有欄位語意。
- shared state payload不含 Room / Campaign / Session / Combat identity。
- End Combat只清規格要求的 death-save / combat bookkeeping;Concentration與其他 persistent state按產品規格保留。
D.1 Spell source / resource
至少用:
- prepared caster。
- known caster。
- multiclass不同 spellcasting ability。
- Pact Magic / normal slots分池。
- upcast。
確認 Cast後正確 pool扣除;duplicate command不重扣。
D.2 AoE
Fireball類 journey:Player選 proposed targets → DM confirm affected list → 同一 RollGroup建立多個 saves → damage依成功/失敗分支套用。Server不出現 radius coordinate / cell計算。
D.3 Concentration
測:
- cast concentration A。
- cast concentration B → A結束。
- damage → CON save request。
- failed save → concentration清除。
- End Combat → concentration仍保留(如果尚未因其他原因結束)。
D.4 Conditions
2014 condition清單逐一至少有:
- registry / definition存在。
- locale存在。
- apply/remove roundtrip。
- 有機械效果者具 focused calculation test。
不能用「Condition名稱可存」代替 mechanical behavior gate。
D.5 Reaction / Ready
測 ReactionRequest reload/reconnect、accept/decline、reaction spent、防 duplicate resolution。Quick OA只有 DM trigger後才建立;Player movement text本身不得自動產生 OA geometry判斷。
E.1 Browser UI
Playwright至少一條 DM + Player journey:
- DM從 Session toolbar Start Combat。
- Party auto include。
- 加 SRD Monster與 Quick Enemy至少各一。
- initiative完成。
- Player自己的 Turn能 Attack;非自己 Turn action disabled / server拒絕。
- 命中後 HP state與 compact Log同步。
- Player UI看不到 exact enemy HP / AC。
- DM UI看得到完整資料。
- Position Note留空仍可跑;填寫後顯示但不影響 rule calculation。
- DM處理一次 range/AoE/OA adjudication。
E.2 Payload secrecy
除了 browser DOM,直接攔 REST / Resume / event / MCP response驗證 forbidden fields不存在。這是 P4 closeout blocker。
E.3 MCP automated protocol
沿 M04的 2026-07-28 modern wire contract測 Combat tools:
- DM catalog含 DM combat tools。
- Player catalog只含 Player合法 combat tools。
- tool call仍每 request重驗 grant / epoch / OAuth authority。
- Take Back / Session End後舊 AI權限對 Combat tool同樣失效。
get_combat_context Player版無 enemy secrets。
E.4 Guide / briefing parity
自動 test確保 tool description、guide、briefing都包含:current turn、action/reaction限制、DM adjudication、resolve後回 wait loop;不能只有其中一處知道 combat workflow。
P4-F — Full P4 Integration & Closeout
F.1 Restart / reconnect
至少一次真 PostgreSQL + app restart整合:
active Combat
Round 4
Player waiting on save or ReactionRequest
→ restart server
→ reconnect Human / AI
→ exact current turn + pending state restored
→ resolve once
不得用 SQLite metadata.create_all當唯一 restart證據。
F.2 Full browser journey
完整 journey至少包含:
- SRD Monster。
- Quick Enemy。
- Initiative。
- weapon attack。
- saving throw或 spell。
- damage / healing。
- condition。
- concentration或 reaction至少一項。
- 0 HP monster由 DM選 outcome。
- Session boundary resume。
- End Combat cleanup。
F.3 Real ChatGPT Web gate
使用現有 M04 connector / OAuth / AI Join Kit,不建立測試專用 AI入口。
最低人工 gate:
AI DM get_session_context
→ Start Quick Combat
→ add enemy / initiative
→ wait_for_event
→ Human or AI Player declares action
→ AI DM / Player uses formal combat tool
→ attack or save + damage resolves on table
→ advance turn
→ at least one further wait/reconnect continuity
→ End Combat
驗收者要在 Adventure Table UI看到實際 Combat state / Log / HP / turn變化;只有 ChatGPT回答文字不算通過。
若 tool call失敗,照既有 M04規則提供實際 tool error,不得用「可能 connector連不上」代替呼叫。
F.4 Regression / closeout evidence
P4 closeout需記錄:
- backend focused + full relevant regression。
- frontend unit + build。
- migration / PostgreSQL tests且無 silent skip。
- Full-Stack E2E workflow run id。
- real ChatGPT Web gate日期、client、角色(DM/Player)、journey結果。
- standalone boundary tests。
- static review finding與處理結果。
P4-A~F都各自完成 closeout後,才進 Phase merge gate。
4. 人工驗收重點
自動測試之外,人眼特別確認:
- Quick Combat仍像桌上跑團,不像 CRPG技能列。
- 不填 Position Note也完全能打。
- 一般 attack不會每次跳 DM confirm。
- 真正有空間歧義時才停給 DM裁定,且裁定 UI簡短。
- Player看敵人時有足夠 fiction feedback,但沒有精確 HP / AC metagame資料。
- DM看敵人資訊清楚,不需要切到大型管理後台。
- Chat不被 modifier / resource細節洗滿;機械結果主要在 compact Log。
- AI DM / Player能從 briefing自行維持 combat loop,不靠 host反覆提醒「再 wait」。
5. P4 closeout blocker
以下任一成立不得關 P4:
- active Combat不能跨 Session resume。
- Player payload可看到 enemy exact HP / AC / hidden resources。
- duplicate attack可造成雙重 state mutation。
- Combat Engine另建第二套 formal roll。
- Quick Combat存在 hidden coordinates / fake range automation。
- core SRD Monster / Beast沒有完整匯入證據。
- Condition只有 UI icon沒有規則效果。
- Human與AI走不同 combat business logic。
- server restart遺失 pending turn / roll / reaction / adjudication。
- standalone被新增 Combat tables/routes污染。
- 真實 ChatGPT Web Combat journey未通過。