Skip to content

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 → ⑦ 기록 Record

These stages never change. What varies is who/when triggers them and what policy governs each.

The six axes (GenerationPolicy, generation-policy.entity.ts)

AxisFieldValuesActive today
1 · Timingtimingahead · at_start · duringat_start (default)
2 · Triggertriggermanual · auto_on_confirm · auto_on_deadlinemanual (default)
3 · Lifecyclelifecyclelive · frozenfrozen (default)
4 · PoolpoolModeall_confirmed · host_selected · opt_inall_confirmed (default)
5 · Recordingrecordingrecorded · casualderives from session.isFriendly (00047: friendly ≠ ELO)
6 · Compositioncompositionrotation · manual · seededrotation (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 casetimingtriggerlifecyclepoolrecordingcomposition
시작 시 생성 (shipped S2a)at_startmanualfrozenall_confirmedrecordedrotation
사전 자동 라이브 (UC1)aheadauto_on_confirm + deadline lockliveall_confirmedrecordedrotation
진행 중 부분 생성 (UC3)duringmanualfrozenhost_selected + opt-outmixedrotation/manual
킹오브코트 · 래더 (shipped P6)*duringmanualrollingall_confirmedrecordedn/a — via styleId
시드 브라켓 (tournament)ahead/at_startmanualfrozenall_confirmedrecordedseeded
기록·캐주얼 혼합anyanyanyanyper-match (nature)any

* King-of-Court/ladder shipped 2026-07-16 via the pre-existing Session.generationStyleIdSTRATEGY_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)

  1. Pool + Recording (UC3) — mid-session subset + per-player opt-out/casual. Mostly UI; reuses isFriendly (session) + nature (per-match). Highest-value, lowest-cost.
  2. Recurrence template — persist a policy, reuse it across a session recurrence.
  3. 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.
  4. Composition — seeded bracketsseeded (tournament) draws. The bracket.rules / swiss.rules / tournament.rules engine strategies already exist. (King-of-Court/ladder was originally planned to activate via this axis's results_driven value; it instead shipped 2026-07-16 via the pre-existing styleIdSTRATEGY_REGISTRY seam + each strategy's own family field — 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).

Markdown remains the source of truth. Run yarn docs:check before handoff.