diff --git a/.codex/skills/soundlog-api-contract-sync/SKILL.md b/.codex/skills/soundlog-api-contract-sync/SKILL.md new file mode 100644 index 0000000..6ac5bd8 --- /dev/null +++ b/.codex/skills/soundlog-api-contract-sync/SKILL.md @@ -0,0 +1,73 @@ +--- +name: soundlog-api-contract-sync +description: Soundlog에서 front-first로 만든 기능의 API 계약을 추출하고, SoundLogTeam/api-docs OpenAPI 문서와 SoundLogServer DTO/validator/service에 반영하는 워크플로우. Use when the user asks to update API docs from frontend/mock work, sync backend DTOs, reflect frontend-first changes into server, or keep SoundLogTeam/api-docs current. +--- + +# Soundlog API Contract Sync + +## Goal + +Keep three surfaces aligned: + +1. `SoundLogApp`: `src/api`, `src/mock-server`, `src/types/domain`, screens/hooks +2. `SoundLogTeam/api-docs`: `openapi/soundlog-api.yaml` +3. `SoundLogServer`: routes, validators, DTO/service responses, seed/mock data + +Use this when a feature was built front-first and backend/API contracts must catch up. + +## Required Workflow + +1. **Update local main branches** + - In `SoundLogApp`, pull latest `main`. + - In sibling repos `../api-docs` and `../SoundLogServer`, pull latest `main` when present. + - Never push directly to SoundLogApp `main`; create a `codex/` branch for app changes. + +2. **Extract frontend contract** + - Inspect changed or relevant files: + - `src/api/*Api.ts`, `src/api/*Queries.ts` + - `src/mock-server/types.ts`, `src/mock-server/*Handlers.ts` + - `src/types/domain.ts` + - affected screens under `app/` and `src/components/` + - local stores that create payloads, especially recommendation/library/moment/session stores + - Classify each contract as `new`, `changed`, `removed`, or `frontend-only`. + +3. **Write API contract** + - Update `../api-docs/openapi/soundlog-api.yaml`. + - Use `templates/endpoint-contract.md` when drafting a new endpoint. + - Keep request/response names stable and backend-friendly. + - Include empty/error states when frontend depends on them. + +4. **Reflect backend DTO** + - Update `../SoundLogServer/src/validators/api.validators.ts` for request/query/body shape. + - Update service DTO response mapping in `src/services/soundlog.service.ts` and `src/services/mock-soundlog.service.ts`. + - Update seed/mock data only when frontend requires concrete demo behavior. + - Avoid Prisma migrations unless the contract truly needs persistence. + +5. **Review** + - Use `references/frontend-contract-extraction.md` and `references/backend-dto-handoff.md`. + - Check that backend can implement from docs without reading frontend code. + - Check that frontend can consume server responses without additional mapping surprises. + +6. **Verify** + - App docs/skill-only changes: `git diff --check` + - API docs: YAML structure smoke check and `git diff --check` + - Server: `pnpm run typecheck` or `npm run typecheck` depending on repo scripts, plus tests if DTO behavior changed + +## Output Expectations + +Report separately: + +- App skill or contract extraction changes +- API docs changes +- Server DTO/validator/service changes +- Verification commands +- Any unresolved backend implementation risk + +## Guardrails + +- Do not invent backend fields only for UI decoration; mark them frontend-only or derive them in a mapper. +- Keep `TravelMode` and `MusicRecommendationMode` distinct. + - `TravelMode`: walk, drive, cafe, ocean, festival, night + - `MusicRecommendationMode`: everyday, travel +- If an app mock response has extra fields, either document them or explicitly call them frontend-only. +- If `api-docs` and server disagree, treat `api-docs` as the handoff contract and update server to match. diff --git a/.codex/skills/soundlog-api-contract-sync/references/backend-dto-handoff.md b/.codex/skills/soundlog-api-contract-sync/references/backend-dto-handoff.md new file mode 100644 index 0000000..b4246af --- /dev/null +++ b/.codex/skills/soundlog-api-contract-sync/references/backend-dto-handoff.md @@ -0,0 +1,28 @@ +# Backend DTO Handoff + +Use this checklist before saying backend DTO reflection is complete. + +## DTO Review + +- Request DTO has all frontend params/body fields. +- Response DTO contains all fields consumed by screens. +- Optional fields are genuinely optional in frontend rendering. +- Enums match frontend string values exactly. +- Server validation accepts comma-separated query arrays when frontend/API docs use CSV. +- Server response envelope matches OpenAPI: `{ data }` for single/list unless paginated. +- Paginated lists return `{ data, page }`. + +## Server Files + +- `src/routes/index.ts`: endpoint exists and method/path matches OpenAPI. +- `src/validators/api.validators.ts`: query/body/params match OpenAPI. +- `src/services/soundlog.service.ts`: real DB DTO mapping matches response schema. +- `src/services/mock-soundlog.service.ts`: mock DB mode matches the same schema. +- `src/data/seed-data.ts`: demo data exists when UI needs meaningful local verification. +- `prisma/schema.prisma`: update only when persistence truly requires a new column/table. + +## Review Prompt + +Ask: "Can a backend developer implement this from `api-docs` without opening the frontend repo?" + +If no, add descriptions, examples, enum notes, or nullable behavior to `openapi/soundlog-api.yaml`. diff --git a/.codex/skills/soundlog-api-contract-sync/references/frontend-contract-extraction.md b/.codex/skills/soundlog-api-contract-sync/references/frontend-contract-extraction.md new file mode 100644 index 0000000..b37a4d2 --- /dev/null +++ b/.codex/skills/soundlog-api-contract-sync/references/frontend-contract-extraction.md @@ -0,0 +1,29 @@ +# Frontend Contract Extraction + +Use this checklist when extracting API needs from SoundLogApp. + +## Read Order + +1. Screen entry under `app/` +2. Query hooks under `src/api/*Queries.ts` +3. API facade under `src/api/*Api.ts` +4. Mock handler and mock params under `src/mock-server` +5. Domain types under `src/types/domain.ts` +6. Event/local stores that create server payloads + +## Contract Questions + +- Which screen or user flow needs this data? +- Is the data currently query-backed, mock-backed, or local-store only? +- Is the field persisted by backend or derived by frontend? +- What happens when the response is empty? +- What happens when nullable fields are missing? +- Are enum values Korean labels or stable English identifiers? +- Does the frontend send a full object in mock mode that must become IDs/query params in HTTP mode? + +## Common Soundlog Decisions + +- `MusicRecommendationMode` is a recommendation scope toggle: `everyday | travel`. +- `TravelMode` is a trip/activity context: `walk | drive | cafe | ocean | festival | night`. +- `MoodRecommendation.playlistId` is optional. If absent, app can play the embedded `track`. +- TourAPI raw fields should not leak to app DTOs; normalize to `PlaceContext`. diff --git a/.codex/skills/soundlog-api-contract-sync/templates/endpoint-contract.md b/.codex/skills/soundlog-api-contract-sync/templates/endpoint-contract.md new file mode 100644 index 0000000..c2b12fe --- /dev/null +++ b/.codex/skills/soundlog-api-contract-sync/templates/endpoint-contract.md @@ -0,0 +1,30 @@ +# Endpoint Contract Template + +## Endpoint + +- Method: +- Path: +- Frontend caller: +- Screen/user flow: +- Auth: + +## Request + +- Path params: +- Query params: +- Body: +- Headers: + +## Response + +- DTO name: +- Required fields: +- Optional fields: +- Empty state: + +## Backend Notes + +- Derived fields: +- Persistence needed: +- Mock/seed data needed: +- Error cases: diff --git a/.codex/skills/soundlog-korean-commit-pr/SKILL.md b/.codex/skills/soundlog-korean-commit-pr/SKILL.md new file mode 100644 index 0000000..2452c7c --- /dev/null +++ b/.codex/skills/soundlog-korean-commit-pr/SKILL.md @@ -0,0 +1,90 @@ +--- +name: soundlog-korean-commit-pr +description: Soundlog 저장소에서 커밋, 푸시, PR 생성, PR 제목/본문 정리를 한국어로 일관되게 수행하는 워크플로우. Use when the user asks to commit, push, create or update a PR, check PR titles, standardize commit/PR wording, or prepare Korean pull requests for SoundLogApp, api-docs, or SoundLogServer. +--- + +# Soundlog Korean Commit PR + +## Goal + +Soundlog 관련 저장소의 변경사항을 안전하게 커밋하고, 한국어로 읽히는 PR을 만든다. + +대상 저장소: + +- `SoundLogApp` +- `SoundLogTeam/api-docs` +- `SoundLogServer` + +## Required Workflow + +1. **상태 확인** + - `git status --short --branch`로 현재 브랜치와 변경 파일을 확인한다. + - `git diff --stat`과 필요한 diff를 읽고, 요청 범위 밖의 변경은 stage하지 않는다. + - `main` 또는 보호 브랜치에 있으면 `codex/` 브랜치를 만든다. + +2. **검증** + - 코드 변경이면 가능한 가장 가까운 검증 명령을 실행한다. + - 문서/스킬 변경이면 최소 `git diff --check`를 실행한다. + - 실행하지 못한 검증은 PR 본문과 최종 응답에 이유를 적는다. + +3. **커밋** + - 커밋 메시지는 반드시 한국어 요약으로 작성한다. + - 형식: `: <한국어 요약>` + - 허용 prefix: + - `feat:` 기능 추가 또는 사용자 경험 변화 + - `fix:` 버그 수정 + - `docs:` 문서, 스킬, API 명세 변경 + - `refactor:` 동작 유지 리팩터링 + - `test:` 테스트 추가/수정 + - `chore:` 설정, 정리, 유지보수 + - `build:` 빌드/패키지 변경 + - `ci:` CI/CD 변경 + - 예시: + - `docs: 한국어 커밋 PR 스킬 추가` + - `feat: 추천 모드 DTO 계약 반영` + - `fix: 웹 권한 모듈 로딩 오류 수정` + +4. **푸시** + - 현재 작업 브랜치만 push한다. + - `SoundLogApp`의 `main`에는 절대 직접 push하지 않는다. + +5. **PR 생성 또는 갱신** + - 기존 PR이 있으면 새 PR을 만들지 말고 해당 PR을 갱신한다. + - PR 제목은 반드시 한국어 conventional 스타일로 쓴다. + - 단일 커밋 PR이면 PR 제목은 커밋 제목과 맞추는 것을 기본값으로 한다. + - 여러 변경이 섞이면 가장 큰 목적을 제목에 둔다. + +6. **PR 제목 검수** + - PR 생성/수정 후 `gh pr view ... --json title,body,url`로 실제 제목을 다시 확인한다. + - 제목이 영어만 있거나 범위가 틀리거나 변경 내용을 충분히 대표하지 못하면 `gh pr edit --title`로 수정한다. + +## PR Body Template + +PR 본문은 한국어로 작성하고, 저장소 템플릿이 없으면 아래 구조를 사용한다. + +```markdown +## 작업 내용 +- 변경한 핵심 내용을 2~4개로 요약 + +## 검증 +- 실행한 명령 또는 확인한 항목 + +## 참고 +- 리뷰어가 알아야 할 제약, 미실행 검증, 연관 PR +``` + +## Multi-Repo PR Rules + +`SoundLogApp`, `api-docs`, `SoundLogServer`를 함께 수정할 때는 각 PR 본문에 연관 PR을 남긴다. + +- 앱 PR: API 문서/서버 PR이 함께 필요한지 적는다. +- API 문서 PR: 기준이 된 프론트 변경 또는 서버 반영 PR을 적는다. +- 서버 PR: 어떤 API 문서 계약을 반영했는지 적는다. + +## Quality Bar + +- 제목만 보고도 변경 목적이 보여야 한다. +- PR 본문은 파일 목록이 아니라 리뷰 관점의 요약이어야 한다. +- 검증 결과는 실제 실행한 명령 그대로 적는다. +- 실패하거나 생략한 검증은 숨기지 않는다. +- 관련 없는 변경이 섞였으면 커밋 전에 분리한다.