Skip to content

M2: Editor & Live — Scoring, Progression, SSE, SVG-Bracket, Sharing - #3

Merged
TimGoldbach merged 1 commit into
feat/m1-platformfrom
feat/m2-editor-live
Jun 15, 2026
Merged

M2: Editor & Live — Scoring, Progression, SSE, SVG-Bracket, Sharing#3
TimGoldbach merged 1 commit into
feat/m1-platformfrom
feat/m2-editor-live

Conversation

@TimGoldbach

Copy link
Copy Markdown
Owner

Setzt Meilenstein M2 (Kern) aus docs/PLAN.md um: den „Turnier-durchspielen"-Loop. Orchestrierter Multi-Agent-Build (4 Slices) + adversariales 5-Perspektiven-Review; Blocker + alle Majors eingearbeitet.

ℹ️ Gestapelt auf #2 (M1). Base ist feat/m1-platform → Diff bleibt M2-only. Retargetet automatisch auf main nach Merge der Vorgänger.

Erstmals echt verifiziert: Die Toolchain ist inzwischen installiert, daher tsc --noEmit grün für shared, api & web + Shared-Tests 2/2. (M0/M1 waren offline nur inspiziert.)

Was drin ist

Backend (apps/api)

  • bracket/progression.ts — pure Winner-Advancement, Bye-Auto-Advance, Round-Robin-Standings (3/1/0, stabiler Tiebreak).
  • tournamentsScoring (Owner oder SCORE-Link) mit Single-Elim-Progression, Bye-Seeding beim Create, Status-Recompute; PATCH /design; @Sse /events über prozess-lokalen EventsService.
  • viewerCanScore wird pro Request abgeleitet → die öffentliche Seite bietet Scoring nur, wenn wirklich berechtigt.

Frontend (apps/web)

  • bracket/ — SVG-BracketView, MatchNode, StandingsTable, StageView, Token→CSS-Var-Mapping + Presets.
  • ScoreableMatch (inline Scoring), SharePanel (Capability-Links), öffentliche Live-View/Score-Route /t/[id]?token=, EventSource-Live-Refresh.
  • Owner-Editor komponiert Bracket + Theme-Controls + Sharing.

Review-Fixes

  • 🔴 Blocker: doppelter events-Identifier im Controller (TS2300) → SSE-Handler umbenannt.
  • 🟠 Re-Scoring abgeschlossener Matches abgelehnt (sonst veraltete Sieger downstream); UI blendet das Formular für COMPLETED aus.
  • 🟠 Round-Robin auf beiden Seiten scorebar (gemeinsame RoundRobinMatches-Komponente).
  • 🟠 Score-Inputs re-syncen bei Live-Updates; geteilter detailKey; Link-Query-Keys aus dem detail-Subtree; Standings-Empty-State; force-dynamic.
  • 🟡 Echte Typfehler (von tsc gefunden & gefixt): unauflösbarer express-Import → minimaler Inline-Request-Typ; nicht existente next-auth/jwt-Augmentation entfernt + Session-Callback abgesichert.

Tooling

pnpm-lock.yaml eingecheckt; onlyBuiltDependencies in pnpm-workspace.yaml gesetzt (prisma/esbuild/sharp), damit pnpm install nicht an ignorierten Build-Skripten scheitert; *.tsbuildinfo + next-env.d.ts ignoriert.

Verschoben auf M2.1/M3 (dokumentiert)

Link-Expiry/Revoke, voller Theme-Editor + Saved-Theme-Bibliothek, Drag-Reseeding, double-elim-Progression, SSE-Multi-Replica.

⚠️ Noch laufzeit zu prüfen

Typecheck ≠ Runtime. Ungetestet zur Laufzeit: der SSE-Stream durch den BFF (EventSource sendet keine Header → Session-Cookie + ?token), der Auth.js-v5-Login/Sync, und das SVG-Bracket-Layout visuell. pnpm --filter @tournamentify/api prisma:migrate für die erste Migration nicht vergessen.

🤖 Generated with Claude Code

…ring

Implements milestone M2 (core) from docs/PLAN.md, built via an orchestrated
multi-agent pass + a 5-lens adversarial review (blocker + all majors folded in).
Unlike M0/M1 this was type-checked for real: the toolchain is now installed, so
`tsc --noEmit` passes for shared, api and web, and the shared tests pass (2/2).

Backend (apps/api):
- bracket/progression.ts: pure winner advancement, bye auto-advance and
  round-robin standings (win=3/draw=1/loss=0, stable tiebreak).
- tournaments: score endpoint (owner or SCORE link) with single-elim
  progression, bye seating on create, status recompute; PATCH /design;
  @sse /events backed by a per-tournament EventsService (process-local).
- viewerCanScore is derived per request so the public page only offers scoring
  when actually authorized.

Frontend (apps/web):
- bracket/: SVG-styled BracketView, MatchNode, StandingsTable, StageView and
  token->CSS-var design mapping with presets.
- ScoreableMatch + inline scoring; SharePanel (capability links); public live
  view/score route /t/[id]?token=; EventSource live refresh hook.
- Owner editor page composes the bracket, theme controls and sharing.

Review fixes:
- Rename the SSE handler (was a duplicate `events` identifier — TS2300 blocker).
- Reject re-scoring a COMPLETED match (would strand advanced winners); the UI
  hides the form for completed matches accordingly.
- Round-robin matches are now scoreable on both owner and public pages via a
  shared RoundRobinMatches component.
- Re-sync score inputs on live updates; share a single detailKey; move link
  query keys out of the detail subtree; standings empty-state; force-dynamic on
  the public route; participantId standings tiebreak.

Type fixes found by tsc: drop the unresolved `express` Request import (minimal
inline request shape); drop the non-existent next-auth/jwt augmentation and
guard the session callback assignments.

Tooling: commit pnpm-lock.yaml; set onlyBuiltDependencies in pnpm-workspace.yaml
(prisma/esbuild/sharp) so installs don't fail on ignored build scripts; ignore
*.tsbuildinfo and next-env.d.ts.

Deferred to M2.1/M3 (see docs/PLAN.md): link expiry/revoke, full theme editor +
saved-theme library, drag-reseeding, double-elim progression, SSE multi-replica.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant