Conventions › Match Generation
Status: Reference — Spine established 2026-07-14 (owner-directed). Only the recording axis is active; every other axis is modeled but returns its default until its feature lands.
Match generation is one pipeline, parameterized by a policy — not a set of separate flows. Every way a club runs matches (generate ahead / at kickoff / mid-session; auto or manual; everyone or a hand-picked few; recorded or casual; rotation or bracket) is the same pipeline read with a different GenerationPolicy. Build the axes as an explicit policy; each new club preference becomes a policy value, not a new code path.
The invariant pipeline
① 대상 Pool → ② 구성 Configure → ③ 생성 Generate → ④ 검토 Review → ⑤ 확정 Commit → ⑥ 시작 Activate → ⑦ 기록 RecordThese stages never change. What varies is who/when triggers them and what policy governs each.
The six axes (GenerationPolicy, generation-policy.entity.ts)
| Axis | Field | Values | Active today |
|---|---|---|---|
| 1 · Timing | timing | ahead · at_start · during | at_start (default) |
| 2 · Trigger | trigger | manual · auto_on_confirm · auto_on_deadline | manual (default) |
| 3 · Lifecycle | lifecycle | live · frozen | frozen (default) |
| 4 · Pool | poolMode | all_confirmed · host_selected · opt_in | all_confirmed (default) |
| 5 · Recording | recording | recorded · casual | derives from session.isFriendly (00047: friendly ≠ ELO) |
| 6 · Composition | composition | rotation · manual · seeded | rotation (default) |
Plus styleId (the 방식 rotation preset, null = format default) and lockAt (when a live draft freezes).
DEFAULT_GENERATION_POLICY encodes the shipped behavior: a host manually makes a frozen draw from all confirmed players via rotation, recorded, at session start. deriveGenerationPolicy(session) returns that default with only recording swapped for friendly sessions. It reads only existing session fields — no persisted policy column, no UI, no behavior change.
Use cases are coordinates, not flows
| Use case | timing | trigger | lifecycle | pool | recording | composition |
|---|---|---|---|---|---|---|
| 시작 시 생성 (shipped S2a) | at_start | manual | frozen | all_confirmed | recorded | rotation |
| 사전 자동 라이브 (UC1) | ahead | auto_on_confirm + deadline lock | live | all_confirmed | recorded | rotation |
| 진행 중 부분 생성 (UC3) | during | manual | frozen | host_selected + opt-out | mixed | rotation/manual |
| 킹오브코트 · 래더 (shipped P6)* | during | manual | rolling | all_confirmed | recorded | n/a — via styleId |
| 시드 브라켓 (tournament) | ahead/at_start | manual | frozen | all_confirmed | recorded | seeded |
| 기록·캐주얼 혼합 | any | any | any | any | per-match (nature) | any |
* King-of-Court/ladder shipped 2026-07-16 via the pre-existing Session.generationStyleId → STRATEGY_REGISTRY seam (registry.ts) + the king_of_court strategy's own live family:'ladder' field — it bypasses the trigger/composition axes entirely rather than setting a GenerationPolicy value. The trigger/composition results_driven members that were reserved for this use case were retired 2026-07-18 as a result (T-17); nothing ever assigned or read them.
Activation path (build one axis at a time)
- Pool + Recording (UC3) — mid-session subset + per-player opt-out/casual. Mostly UI; reuses
isFriendly(session) +nature(per-match). Highest-value, lowest-cost. - Recurrence template — persist a policy, reuse it across a session recurrence.
- Timing + Trigger (UC1) — auto-generation. Needs a regen trigger (server hook on RSVP change, or an edge fn at the deadline) + lock semantics + member-facing provisional draws. Build when a club asks.
- Composition — seeded brackets —
seeded(tournament) draws. Thebracket.rules/swiss.rules/tournament.rulesengine strategies already exist. (King-of-Court/ladder was originally planned to activate via this axis'sresults_drivenvalue; it instead shipped 2026-07-16 via the pre-existingstyleId→STRATEGY_REGISTRYseam + each strategy's ownfamilyfield — P6, superseding this plan. See the use-case table footnote above and T-17.)
Principle: the engine (generateAllRounds, pure) stays composition-agnostic; the policy makes the axes explicit; orchestration invokes the engine per policy; surfaces (참여 CTA · preview · board) adapt to the policy. One implementation per pattern.
Full rationale + the architecture artifact: the S2 design discussion (2026-07-14).