adventure-table

P2-F Closeout Checklist

P2-F — Full P2 Integration & Closeout scope。編號對應 實作規格「P2-F 關門條件」的 21 條。

P2-F 不新增產品行為。這個 Subphase 的工作是把 P2-A~P2-E 累積下來的整合、隔離、遷移、併發與 browser 層缺口補完,並確認整條 Room → Campaign → Roster → Seat → Lobby → Session 的路徑在真後端與真瀏覽器上成立。

Migration

Web journeys

Permission / concurrency

Standalone / baseline

關門過程中修正的問題

Web 從未真正能用 Session 頁面。 meta.pybuild_capabilities() 只設了 room / campaign / seat,漏掉 session,所以 web channel 一直回 session: false。P2-E 的 review 修正把 /rooms/{id}/campaigns/{cid}/sessions/{sid} 明確 gate 成 session capability(見 P2-E closeout「關門過程中修正的問題」第 3 點),兩者相加的結果是:任何瀏覽器一進 Session 頁只會看到 standalone capability boundary 的「This feature is not available here」,Session API 正常但 UI 完全不可達。

這個缺口在 P2-E 沒有被抓到,因為當時沒有任何 Session 的 browser 證據,而前端單元測試是餵 mock capability snapshot。P2-F 新增的 Journey 5 / 6 / 8 一跑就三條同時紅在同一個 assertion 上,正是這條缺陷。

修法是 session=channel == "web" 一行,並把兩條原本斷言 session is False 的測試翻正:test_m03e_capabilities.py::test_web_capabilities_enable_p2_multiplayer_surface(HTTP 層)與 test_p2c_capabilities.py::test_web_channel_advertises_p2_multiplayer_capabilities(direct contract)。standalone 側維持六個 multiplayer flag 全 false,未放寬。

Verification evidence

分支 p2-f-full-integration-closeout,final code SHA 22220df

Branch / final code SHA
  p2-f-full-integration-closeout @ 22220df
  (p2-f-full-integration-closeout-work 為同一棵樹的鏡像分支,內容一致)

Alembic heads
  0009_p2a_character_head (character) (head)
  0014_p2e_sessions (web) (head)
  P2-F 未新增 migration。standalone SQLite 仍只升 character@head。

Backend pytest
  1111 collected / 182 files
  1100 passed, 11 skipped, 0 failed, exit 0
  cwd apps/server,直譯器 ..\..\.venv\Scripts\python.exe
  11 個 skip 全部是缺 PostgreSQL URL 的 gated 測試
  (test_p2a_postgres_migration.py ×2、test_p2b_postgres_workspace.py ×3、
    test_p2e_postgres_sessions.py ×3、test_p2f_postgres_seat_selection.py ×1、
    test_m03b_migration.py ×1、test_m03c_migration.py ×1),
  全數改由下方 CI 的 postgres-migrations job 覆蓋。

CI P2 Non-E2E(正式 workflow evidence)
  run id 34181507756 @ 22220df(exact final code SHA)
  https://github.com/shellpig/adventure-table/actions/runs/34181507756
  conclusion success;backend / frontend / postgres-migrations /
  windows-standalone 四個 job 全綠。
  postgres-migrations 在真 PostgreSQL 上跑
  test_p2a_postgres_migration.py + test_p2b_postgres_workspace.py
  + test_p2e_postgres_sessions.py + test_p2f_postgres_seat_selection.py
  + test_m03c_migration.py。
  windows-standalone 跑 scripts\build-standalone.cmd 與
  scripts\smoke_standalone.py(frozen distribution smoke)。
  前一個 run 34175760850 @ 560fdd9 亦為 success,但當時 Session capability
  缺陷尚未修,該 SHA 的完整 E2E 為紅,不可作為關門證據。

Frontend unit
  219 passed / 47 files,exit 0 @ 22220df

TypeScript / build
  npm run build(tsc --noEmit && vite build)exit 0 @ 22220df

Full Web Playwright
  npm run test:e2e:docker exit 0 @ 22220df
  第一輪 111 tests:108 passed / 0 failed / 3 skipped(7.4m)
  第二輪 xge-less M03-C 子集:7 passed(6.2s)
  3 個 skip:m01j-subclass-expansion.spec.ts 的 direct-vs-sequential 等價
  (KI-M01J-001 intentional fixme,不計入 P2-F 功能證據),以及
  m03c-character-import.spec.ts 兩條需要缺 pack 後端的案例——後者正是
  第二輪跑的那批,已在該輪通過。
  執行前先 docker compose up -d --build server,確保後端是 22220df;
  test:e2e:docker 本身只 rebuild web service。

docker compose config
  exit 0

Human smoke
  使用者於 2026-09-08 在本機執行並確認通過,未回報 blocker。
  本文件不代為記錄逐步操作紀錄。

驗收條目 → 測試對應

條目 證據
1, 2 test_p2a_postgres_migration.py 兩條(CI postgres-migrations);test_m03d_migration_sqlite.pytest_m03d_sqlite_fk.py
3 test_m03d_schema_parity.py::test_sqlite_character_migration_schema_matches_character_metadatatest_p2a_migration_tracks.pytest_m03c_migration.py(P2-F 起進 CI)
4 test_p2a_workflow_contract.py::test_p2f_final_non_e2e_workflow_closes_postgres_and_standalone_gates;run 34181507756
5 character-builder.spec.tsp1f-character-creation.spec.tsp1g-level-up.spec.tsp2a-room-bootstrap.spec.ts(全部經 roomTest fixture 走 Room namespace)
6 m03c-character-import.spec.ts(兩輪)、test_p2a_legacy_fixture.pytest_p2a_character_json_v1.py
7, 18 test_m03g_roundtrip.pytest_m03g_standalone_runtime.pytest_m03g_import_edges.pytest_m03_import_boundary.pytest_p2a_room_import_boundary.pytest_p2a_standalone_room_boundary.py
8 test_p2b_room_character_api.py::test_room_a_cannot_use_room_b_character_or_draft_idstest_p2c_campaign_policy.pytest_p2d_seat_policy.pytest_p2e_late_join.py::test_late_join_revalidates_same_room_even_if_persistence_is_tampered
9 p2f-cross-campaign.spec.ts::P2-F Journey 7 shares rich Character State across two Campaign roster contextstest_p2c_campaign_integration.py
10 test_p2a_room_access.py 十二條
11 test_p2d_seat_policy.pyp2d-lobby-seats.spec.ts 兩條
12 test_p2e_session_persistence.py::test_session_referenced_seat_cannot_hard_delete_but_can_archivetest_p2f_restart_integration.py(restart 後歷史 Seat 與 participant 仍在)
13 test_p2e_postgres_sessions.py 三條(CI)、p2f-cross-campaign.spec.ts::P2-F Journey 8 shows a localized browser conflict for cross-Campaign active Character collision
14 p2f-session-lifecycle.spec.ts::P2-F Journey 5 starts and ends a real Session from the browser::P2-F Journey 6 selects a Character after Start and Late Joins through the browsertest_p2e_session_lifecycle.pytest_p2e_late_join.py
15 test_p2e_end_state_preservation.py::test_end_session_preserves_exact_rich_character_state_and_history
16 test_p2e_room_hard_delete.py::test_room_hard_delete_removes_session_restrict_graph_before_owned_historytest_p2c_room_hard_delete.py
17 hardcodedUiCopy.test.tssessionMessages.test.tsseatMessages.test.tsp2eRequestMessages.test.tsRoomSessionPage.test.tsRoomLobbyPage.test.tsRoomCampaignPage.test.tsm02h-bilingual-site-smoke.spec.tsm02h-localization-state-integrity.spec.ts
19 P2 Non-E2Ewindows-standalone job @ 34181507756;test_p2a_workflow_contract.py::test_p2f_final_non_e2e_workflow_closes_postgres_and_standalone_gates
20 全套 backend pytest 1100 passed;全套 Playwright 108 passed
21 test_p2f_restart_integration.py::test_p2f_restart_preserves_full_room_campaign_session_workspace_graphtest_p2f_postgres_seat_selection.py::test_concurrent_seat_selection_has_one_database_winner(CI)、test_p2e_live_character_scope.py 三條、human smoke
Session capability 修正 test_m03e_capabilities.py::test_web_capabilities_enable_p2_multiplayer_surfacetest_p2c_capabilities.py::test_web_channel_advertises_p2_multiplayer_capabilitiesroutes.test.ts

承接 P2-E 的未結清項目

Boundary

已知限制

Handoff

P2-F 已完成,P2 — Room / Campaign / Session / Seat 關門。下一步是 P3 — Exploration + Roll + AI

P3 可以直接假設下列基礎已存在,不要重造: