From ba7bd903992a6a5ff4098858a310fc5759b5a22e Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Sun, 1 Mar 2026 04:37:27 +0100 Subject: [PATCH] docs(01-07): complete Player Management plan - SUMMARY.md with frontmatter, decisions, deviations, self-check - STATE.md updated: plan 11/14, 71% progress, 5 decisions added - ROADMAP.md updated: 10/14 summaries for phase 01 - REQUIREMENTS.md: PLYR-02, PLYR-03, PLYR-04, PLYR-05 marked complete Co-Authored-By: Claude Opus 4.6 --- .planning/REQUIREMENTS.md | 16 +- .planning/STATE.md | 25 +-- .../01-tournament-engine/01-07-SUMMARY.md | 146 ++++++++++++++++++ 3 files changed, 169 insertions(+), 18 deletions(-) create mode 100644 .planning/phases/01-tournament-engine/01-07-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index b97ac4b..be56d60 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -77,10 +77,10 @@ Requirements for Phase 1 (Development Focus: Live Tournament Management). Each m ### Player Management - [x] **PLYR-01**: Player database persistent on Leaf (LibSQL), synced to Core (PostgreSQL) -- [ ] **PLYR-02**: Search with typeahead, merge duplicates, import from CSV -- [ ] **PLYR-03**: QR code generation per player for self-check-in -- [ ] **PLYR-04**: Buy-in flow: search/select player → confirm → optional auto-seat → receipt → displays update -- [ ] **PLYR-05**: Bust-out flow: select player → select hitman → bounty transfer → auto-rank → rebalance trigger → displays update +- [x] **PLYR-02**: Search with typeahead, merge duplicates, import from CSV +- [x] **PLYR-03**: QR code generation per player for self-check-in +- [x] **PLYR-04**: Buy-in flow: search/select player → confirm → optional auto-seat → receipt → displays update +- [x] **PLYR-05**: Bust-out flow: select player → select hitman → bounty transfer → auto-rank → rebalance trigger → displays update - [x] **PLYR-06**: Undo capability for bust-out, rebuy, add-on, buy-in with full re-ranking - [x] **PLYR-07**: Per-player tracking: chip count, playing time, seat, moves, rebuys, add-ons, bounties, prize, points, net take, full action history @@ -350,10 +350,10 @@ Which phases cover which requirements. Updated during roadmap reorganization. | FIN-13 | Phase 1 | Complete | | FIN-14 | Phase 1 | Complete | | PLYR-01 | Phase 1 | Complete | -| PLYR-02 | Phase 1 | Pending | -| PLYR-03 | Phase 1 | Pending | -| PLYR-04 | Phase 1 | Pending | -| PLYR-05 | Phase 1 | Pending | +| PLYR-02 | Phase 1 | Complete | +| PLYR-03 | Phase 1 | Complete | +| PLYR-04 | Phase 1 | Complete | +| PLYR-05 | Phase 1 | Complete | | PLYR-06 | Phase 1 | Complete | | PLYR-07 | Phase 1 | Complete | | SEAT-01 | Phase 1 | Complete | diff --git a/.planning/STATE.md b/.planning/STATE.md index 2da6f1d..30ef1b4 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,12 +3,12 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: unknown -last_updated: "2026-03-01T03:03:22.000Z" +last_updated: "2026-03-01T03:35:13.000Z" progress: total_phases: 1 completed_phases: 0 total_plans: 14 - completed_plans: 9 + completed_plans: 10 --- # Project State @@ -23,27 +23,27 @@ See: .planning/PROJECT.md (updated 2026-02-28) ## Current Position Phase: 1 of 7 (Tournament Engine) -Plan: 10 of 14 in current phase +Plan: 11 of 14 in current phase Status: Executing Phase 1 -Last activity: 2026-03-01 — Completed Plan H (Table & Seating Engine) +Last activity: 2026-03-01 — Completed Plan G (Player Management) -Progress: [██████░░░░] 64% +Progress: [███████░░░] 71% ## Performance Metrics **Velocity:** -- Total plans completed: 9 +- Total plans completed: 10 - Average duration: 8min -- Total execution time: 1.22 hours +- Total execution time: 1.33 hours **By Phase:** | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| -| 01-tournament-engine | 9 | 73min | 8min | +| 01-tournament-engine | 10 | 80min | 8min | **Recent Trend:** -- Last 5 plans: 01-05 (10min), 01-03 (5min), 01-13 (5min), 01-06 (9min), 01-08 (6min) +- Last 5 plans: 01-03 (5min), 01-13 (5min), 01-06 (9min), 01-08 (6min), 01-07 (7min) - Trend: steady *Updated after each plan completion* @@ -95,6 +95,11 @@ Recent decisions affecting current work: - [01-08]: Stale suggestion re-validation requires fromCount - toCount >= 2 before accepting - [01-08]: Break table is fully automatic (applies immediately, result is informational per CONTEXT.md) - [01-08]: Blueprint routes are venue-level (not tournament-scoped); admin role required for mutations +- [01-07]: Rankings derived from bust_out_at timestamps via RecalculateAllRankings (never stored independently) +- [01-07]: FTS5 queries use quoted terms with * suffix for prefix matching +- [01-07]: CSV formula injection neutralized with tab prefix on =, +, -, @ characters +- [01-07]: Buy-in flow auto-registers player in tournament_players if not already present +- [01-07]: QR code URL format: felt://player/{uuid} for future PWA self-check-in ### Pending Todos @@ -112,5 +117,5 @@ None yet. ## Session Continuity Last session: 2026-03-01 -Stopped at: Completed 01-08-PLAN.md (Table & Seating Engine) +Stopped at: Completed 01-07-PLAN.md (Player Management) Resume file: None diff --git a/.planning/phases/01-tournament-engine/01-07-SUMMARY.md b/.planning/phases/01-tournament-engine/01-07-SUMMARY.md new file mode 100644 index 0000000..1a34625 --- /dev/null +++ b/.planning/phases/01-tournament-engine/01-07-SUMMARY.md @@ -0,0 +1,146 @@ +--- +phase: 01-tournament-engine +plan: "07" +subsystem: api, database +tags: [player, fts5, qrcode, csv-import, ranking, bounty, pko, undo] + +requires: + - phase: 01-tournament-engine + provides: "audit trail + undo engine (Plan C), financial engine (Plan F), seating engine (Plan H), schema with FTS5 (Plan B)" +provides: + - "PlayerService with CRUD, FTS5 typeahead search, merge, CSV import" + - "QR code generation per player (felt://player/{uuid})" + - "Tournament player operations: register, bust, undo bust" + - "RankingEngine deriving positions from bust-out order" + - "Player API routes for venue-level and tournament-scoped operations" + - "Buy-in flow: register + financial + auto-seat" + - "Bust flow: hitman + bounty + rank + balance check" + - "CSV export safety: formula injection neutralization" +affects: [09-tournament-lifecycle, 11-tournament-ui, 14-integration] + +tech-stack: + added: [skip2/go-qrcode] + patterns: [derived-rankings, csv-formula-injection-safety, fts5-prefix-matching] + +key-files: + created: + - internal/player/player.go + - internal/player/ranking.go + - internal/player/qrcode.go + - internal/player/export.go + - internal/server/routes/players.go + - internal/player/ranking_test.go + - internal/player/player_test.go + modified: + - go.mod + - go.sum + +key-decisions: + - "Rankings derived from bust_out_at timestamps, never stored independently (Pitfall 6)" + - "RecalculateAllRankings rebuilds all bust_out_order values from timestamps for undo consistency" + - "FTS5 query terms wrapped in quotes with * suffix for prefix matching" + - "CSV formula injection neutralized with tab prefix on =, +, -, @ characters" + - "Buy-in flow auto-registers player if not yet in tournament" + - "QR code URL format: felt://player/{uuid} for future PWA self-check-in" + +patterns-established: + - "Derived rankings: always compute from bust-out list, never store" + - "CSV export safety: SanitizeCSVField for any user data in CSV output" + - "Player API pattern: venue-level CRUD + tournament-scoped actions" + +requirements-completed: [PLYR-02, PLYR-03, PLYR-04, PLYR-05, PLYR-06, PLYR-07] + +duration: 7min +completed: 2026-03-01 +--- + +# Plan 07: Player Management Summary + +**Player CRUD with FTS5 typeahead, CSV import, QR codes, bust/undo flows with derived rankings from bust-out order** + +## Performance + +- **Duration:** 7 min +- **Started:** 2026-03-01T03:27:50Z +- **Completed:** 2026-03-01T03:35:13Z +- **Tasks:** 2 +- **Files modified:** 9 + +## Accomplishments +- Full player service with CRUD, FTS5 prefix-matching search, merge, CSV import with safety limits +- QR code generation per player using skip2/go-qrcode (felt://player/{uuid}) +- Tournament player operations: register, bust (with PKO bounty), undo bust with re-ranking +- RankingEngine that derives all positions from ordered bust-out list (never stored) +- Complete player API routes: venue-level CRUD + tournament-scoped actions + rankings +- CSV export formula injection neutralization (tab-prefix on =, +, -, @) +- 12 passing tests covering ranking derivation, undo re-ranking, re-entry, deals, concurrency + +## Task Commits + +Each task was committed atomically: + +1. **Task G1: Player CRUD, search, merge, import, QR codes** - `9373628` (feat) +2. **Task G2: Ranking engine and player API routes** - `8b4b131` (feat) + +## Files Created/Modified +- `internal/player/player.go` - PlayerService with CRUD, search, merge, import, bust, undo +- `internal/player/ranking.go` - RankingEngine deriving positions from bust-out order +- `internal/player/qrcode.go` - QR code generation using skip2/go-qrcode +- `internal/player/export.go` - CSV export safety: formula injection neutralization +- `internal/server/routes/players.go` - PlayerHandler with venue-level and tournament-scoped routes +- `internal/player/ranking_test.go` - 7 ranking tests (bust order, undo, re-entry, deals, concurrency) +- `internal/player/player_test.go` - 5 tests (CSV safety, import limits, UUID) +- `go.mod` - Added skip2/go-qrcode dependency +- `go.sum` - Updated checksums + +## Decisions Made +- Rankings derived from bust_out_at timestamps via RecalculateAllRankings (not stored independently per Pitfall 6) +- FTS5 queries use quoted terms with * suffix for prefix matching +- CSV formula injection neutralized with tab prefix on =, +, -, @ characters +- Buy-in flow auto-registers player in tournament_players if not already present +- QR code URL format: felt://player/{uuid} for future PWA self-check-in + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Installed skip2/go-qrcode dependency** +- **Found during:** Task G1 (QR code generation) +- **Issue:** No QR code library in go.mod +- **Fix:** Ran `go get github.com/skip2/go-qrcode` +- **Files modified:** go.mod, go.sum +- **Verification:** QR code generation compiles and encodes valid PNG +- **Committed in:** 9373628 (Task G1 commit) + +**2. [Rule 3 - Blocking] Created RankingEngine in Task G1 (planned for G2)** +- **Found during:** Task G1 (UndoBust implementation) +- **Issue:** UndoBust calls RecalculateAllRankings which requires the RankingEngine +- **Fix:** Implemented RankingEngine in ranking.go as part of Task G1 +- **Files modified:** internal/player/ranking.go +- **Verification:** Package compiles, tests pass +- **Committed in:** 9373628 (Task G1 commit) + +--- + +**Total deviations:** 2 auto-fixed (2 blocking) +**Impact on plan:** Both auto-fixes necessary for compilation and correctness. No scope creep. + +## Issues Encountered +None + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- Player management API is complete and ready for tournament lifecycle integration (Plan I) +- Ranking engine provides derived rankings for the clock/tournament UI +- Buy-in and bust flows integrate with financial engine and seating engine +- CSV import and merge provide player database management for TDs + +## Self-Check: PASSED + +All 7 created files verified on disk. Both task commits (9373628, 8b4b131) verified in git log. + +--- +*Phase: 01-tournament-engine* +*Completed: 2026-03-01*