Imported from TennisFolio/TennisFolio (
AGENTS.md). Install upstream withnpx skills add TennisFolio/TennisFolio. Copyright stays with the author.
Codex Instructions
This repository is a Spring Boot application for TennisFolio.
Before changing code, read the documents that are relevant to the task:
- Root-level Korean markdown files: product/domain overview and shared vocabulary.
src/main/java/com/tennisfolio/Tennisfolio/matching/ENTITY_DESIGN.md: competition, entry, game, and schedule design notes.
If a document appears garbled because of encoding, do not guess from broken text. Use the current source code and ask for clarification when the rule is important.
Domain Language
Use these terms consistently in the matching module:
Competition: the user-created competition/tournament unit. This is the main external resource and aggregate root for the local matching feature.CompetitionEntry: a participant entry in a competition.Game: a generated or recorded game inside a competition.Schedule: the generated arrangement of games. Use this for generated plans/results, not for the external creation resource.Matching: the internal algorithmic concern of making fair game combinations. Do not use it for controller names, application service names, or external API resource names.
API Naming
- Create competitions with
POST /api/competitions. - Do not use
POST /api/matchesfor competition creation. - Reserve
/matchesor/gamesstyle resources for actual game/match lookup or management. - Competition creation responses should return only the identifiers needed by the client:
publicIdeditToken
Java Naming
- Controller:
CompetitionController - Application command service:
CompetitionCommandService - Request DTO:
CompetitionCreateRequest - Response DTO:
CompetitionCreateResponse - Creation method:
createCompetition - Schedule generation method:
generateSchedule
Keep Matching names inside algorithm/domain internals only when they describe candidate generation or match type logic, for example MatchCandidate or MatchType.
Entity Mapping Notes
tb_competition.PUBLIC_IDmaps toCompetition.publicId.tb_competition.EDIT_TOKENmaps toCompetition.editToken.publicIdis the URL-safe public identifier.editTokenis the client-held edit authorization token.
Working Rules
- Prefer existing package structure and coding style.
- Keep refactors scoped to the requested domain boundary.
- Do not rename generated or unrelated legacy modules unless the task requires it.
- Do not create git commits by default. Only commit changes when the user explicitly asks for a commit.
- Even when the user has asked for a commit, show the staged file list, test/verification result, and commit message first, then ask for confirmation before running
git commit. - When the user asks to develop a feature or proceed with a phase, read
docs/workflows/development-workflow.mdfirst and follow that workflow before making implementation changes. - Write documents under
docs/superpowers/specsanddocs/superpowers/plansin Korean unless the user explicitly asks for another language. - When editing Competition UI styles, follow
docs/competition-design-system.mdand use CSS variables fromsrc/tennisFolio/src/styles/competition-theme.css. Do not introduce new hard-coded Competition colors unless the design system document and theme variables are updated in the same change. - When doing frontend development, do not create or update frontend test code by default. Only write frontend tests when the user explicitly asks for test code.
- When doing screen/frontend development, do not run frontend tests after implementation by default. Only run frontend tests when the user explicitly asks for testing or grants permission for that specific test command.
- Do not run Java/Gradle builds or npm builds by default. This includes
.\gradlew.bat compileJava,.\gradlew.bat compileTestJava,.\gradlew.bat build,npm run build, and similar build commands. - Only run Java/Gradle or npm build commands when the user explicitly asks for verification, asks to run a build/test, or grants permission for that specific command.
- When build verification is skipped because of this rule, state that it was skipped in the final response.
Service Method Composition
Keep application service methods readable as a sequence of business steps.
- A public use-case method should primarily orchestrate the flow: normalize or validate input, load required state, apply changes, and handle removal or follow-up work.
- Extract non-trivial validation, lookup/mapping, create-or-update, and deletion behavior into clearly named private methods so the high-level flow is visible at a glance.
- Name extracted methods by their domain action, such as
validateSkillTiers,findExistingById,saveOrUpdateSkillTiers, andremoveDeletedSkillTiers. - Do not split trivial one-line expressions solely to increase method count; extract when it clarifies a distinct responsibility or a meaningful business step.
Frontend Component Refactoring
When a frontend page grows large, split components by responsibility instead of leaving all JSX in the page file.
- Keep page files focused on data loading, state, event handlers, navigation, and high-level composition.
- Extract UI that is shared by multiple pages into
components/<domain>/shared. - Extract page-specific sections into
components/<domain>/<page-role>folders, for examplecomponents/meeting/publicandcomponents/meeting/manage. - Prefer section-sized components such as
OverviewPanel,AttendancePanel,OperationsPanel, andEntryScreenbefore splitting into tiny input/button components. - Extract repeated UI primitives only when they are reused or clarify intent, for example status option buttons, participant fields, roster panels, summary chips, and confirm modals.
- Move pure formatting, grouping, counting, and normalization helpers into a colocated utility module such as
components/<domain>/shared/<domain>Utils.js. - Move browser-only persistence helpers into the page-role folder that owns the behavior, for example public attendance
localStoragehelpers undercomponents/meeting/public. - Use props to express page-specific behavior on shared components rather than duplicating markup. For example, a shared roster chip can accept optional select/remove handlers.
- Avoid over-splitting into one-off wrappers when the extracted component would only pass through many props and hide simple JSX.
- After moving files, update imports and verify there are no stale imports from the old component root.