Imported from guraband/fish-waffle-tycoon (
AGENTS.md). Install upstream withnpx skills add guraband/fish-waffle-tycoon. Copyright stays with the author.
AGENTS.md
목적
- 이 저장소는
index.html,styles.css,app.js로 구성된 정적 웹 게임 프로토타입이다. - 프레임워크, 번들러, 패키지 매니저, 테스트 러너가 없다.
- 변경은 항상 현재 구조를 존중하는 작은 수술식 수정으로 진행한다.
- 근거 파일:
README.md,index.html,app.js,styles.css,.github/workflows/deploy.yml.
에이전트 응답 규칙
- 모든 사용자-facing 답변과 진행 상황 설명은 한국어로 작성한다.
- 모든 답변은 정확히
네, NG님!으로 시작한다. - 작업 전후 설명은 짧고 구체적으로 쓴다.
- 추측하지 말고, 파일 근거를 확인한 뒤 판단한다.
커밋 트리거 규칙
- 사용자가 정확히
커밋해줘또는commit이라고 말한 경우에만 커밋 플로를 실행한다. - 해당 트리거가 오면
git add .으로 변경 사항을 스테이징한다. - 커밋 메시지는 방금 작업한 내용을 짧게 요약한 한국어 문장으로 작성한다.
- 그다음 해당 메시지로
git commit을 실행한다. - 위 플로는 사용자가 명시적으로 트리거 문구를 준 경우에만 적용한다.
- 사용자가 정확히
push또는푸시해줘라고 말하면 커밋 플로를 먼저 수행한 뒤git push까지 진행한다. push/푸시해줘규칙도 사용자가 해당 트리거 문구를 직접 말한 경우에만 적용한다.
저장소 구조
index.html: 단일 HTML 엔트리 포인트.#app에 앱을 마운트한다.app.js: 전체 게임 상태, 렌더링, 액션 디스패치, 저장 로직이 들어 있는 IIFE 파일.styles.css: 모바일 우선 스타일, 테마 변수, 애니메이션, 반응형 규칙.docs/: PRD와 UI 메모. 구현 의도를 이해할 때 참고한다..github/workflows/deploy.yml: S3 정적 배포 자동화 파일.
실행, 빌드, 테스트
- 개발 서버:
python3 -m http.server 8000 - 대체 실행:
python -m http.server 8000 - 브라우저 주소:
http://localhost:8000 - 직접
index.html을 열 수도 있지만,localStorage확인은 로컬 서버가 더 안전하다. - 빌드 명령은 없다. 정적 파일 그대로 배포한다.
- 린트 명령은 없다.
eslint,prettier,biome설정 파일도 없다. - 테스트 명령은 없다. 테스트 프레임워크와 테스트 파일도 없다.
- 단일 테스트 실행 명령도 없다. 현재는 수동 검증이 기본이다.
검증 기본 절차
- 정적 서버를 띄운 뒤 홈, 게임, 업그레이드, 결과, 설정 모달 흐름을 점검한다.
localStorage저장,이어하기,처음부터 다시가 정상 동작하는지 확인한다.- 모바일 세로 레이아웃과 폭 399px 이하 반응형을 함께 확인한다.
reducedMotion토글이body.reduce-motion과 실제 애니메이션 비활성화로 이어지는지 본다.- 배포 관련 변경이면
.github/workflows/deploy.yml의 S3 sync 규칙과 충돌 없는지 확인한다.
기능별 수동 검증 예시
- 조리 로직 수정 시: 새 게임 시작 -> 반죽 붓기 -> 속 넣기 -> 뒤집기 -> 꺼내기 -> 서빙까지 한 루프를 직접 재생한다.
- 저장 로직 수정 시: 플레이 중 새로고침 ->
이어하기복구 확인 ->처음부터 다시초기화 확인. - UI 수정 시: 홈, 게임, 업그레이드, 결과 화면을 모두 확인하고 작은 화면에서도 버튼이 보이는지 확인한다.
배포와 보조 규칙 파일
- CI 배포는 GitHub Actions가
aws s3 sync로 수행한다. - 배포 워크플로는
main과master푸시에 반응한다. - 정적 자산은 긴 캐시,
index.html은 재검증 캐시 정책을 사용한다. - 로컬 배포 스크립트는 없다.
.cursorrules파일이 없다..cursor/rules/디렉터리가 없다..github/copilot-instructions.md파일이 없다.- 따라서 이 문서가 저장소의 사실상 에이전트 작업 기준서다.
코드베이스 특성
- JavaScript는
(() => { ... })();IIFE 내부에 모두 들어 있다. - 렌더링은 템플릿 문자열과
app.innerHTML교체 방식으로 이뤄진다. - 이벤트는 개별 바인딩보다 문서 레벨 위임(
data-action)을 사용한다. - 상태는 전역
state객체 하나로 관리한다. - 지속 상태와 일시 상태를 분리하고
hydrateTransientState()로 보정한다.
변경 원칙
- 구조를 크게 바꾸기보다 기존 패턴에 맞춰 함수 추가 또는 수정으로 해결한다.
- 새 도구 도입은 정말 필요할 때만 한다. 패키지 추가는 기본 선택지가 아니다.
- UI를 바꿀 때는 모바일 우선, 세로 플레이, 따뜻한 겨울 포장마차 톤을 유지한다.
- 문구, 뱃지, 버튼 라벨은 현재처럼 한국어 중심 UI를 유지한다.
JavaScript 가이드
- 현재 런타임 코드에는
import/export가 없다. 새 기능도 우선은 단일 IIFE 내부에 통합한다. - 파일 분리가 꼭 필요하지 않다면 모듈 시스템을 도입하지 않는다.
- 상수 데이터는 파일 상단의
const객체로 선언한다. 예:DAY_CONFIG,MENU_DATA,UPGRADE_DATA. - 함수 선언은 대부분
function name(...) {}형태를 사용한다. - 함수와 변수는 camelCase를 쓴다. Boolean 성격 함수는
is,has,can,should접두를 우선 검토한다. - 상태 문자열은 기존 값과 맞춘다. 예:
home,game,dayEnd,clear,burnt. - 컬렉션 생성은
Array.from,map,filter,reduce를 자주 사용한다. - 범위 보정은
clamp()같은 유틸을 재사용한다.
포매팅 규칙
- 기존 파일의 들여쓰기, 줄바꿈, 세미콜론 사용을 그대로 따른다.
- 자동 포매터가 없으므로 수동 일관성이 중요하다.
- 긴 템플릿 문자열은 여러 줄로 나누되 HTML 구조가 읽히도록 맞춘다.
- 객체와 배열은 후행 쉼표를 유지하는 현재 스타일을 따른다.
- 인라인 스타일이나 하드코딩 문자열을 늘리기보다 기존 유틸, 상수, CSS 변수로 흡수한다.
상태, 렌더링, 이벤트 규칙
- 루트 상태 shape는
createNewRootState()를 기준으로 유지한다. - Day 전용 상태 shape는
createDayState()를 기준으로 유지한다. - 저장 가능한 값만
localStorage에 들어가게 한다. - 토스트, 모달 열림 상태 같은 UI 일시 상태는 hydrate 단계에서 재설정할 수 있게 유지한다.
- 상태 변경 후에는
saveAndRender()또는 그에 준하는 흐름을 사용한다. - 화면 단위는
renderHomeScreen,renderGameScreen처럼render*함수로 분리한다. - 작은 조각도
render*Card,render*Modal,render*SVG같은 이름을 사용한다. - 템플릿 문자열 안에 조건부 렌더링을 직접 넣는 현재 방식을 유지한다.
- 사용자 입력이 들어가는 문자열은
escapeHtml()로 이스케이프한다. - SVG는 인라인 문자열 반환 패턴을 유지한다.
- 새 액션을 만들면
dispatchAction()의switch에 케이스를 추가한다. - 클릭 처리는
data-action기반 디스패치에 연결한다. - 중복 입력 방지는 pointer lock 패턴을 먼저 살핀 뒤 일관되게 확장한다.
- 스크롤 제어는 필요한 영역에만 제한적으로 넣는다.
에러 처리와 데이터 규칙
- 저장/로드처럼 실패 가능한 브라우저 API는
try/catch로 감싼다. catch는 비우지 않는다.console.error("...", error)패턴을 유지한다.- 조작 불가 상태는 예외를 던지기보다 early return과 토스트 메시지로 처리한다.
- 존재하지 않을 수 있는 참조는 방어적으로 확인한다. 예:
if (!state.activeDay) return;. - 이 프로젝트는 TypeScript를 사용하지 않는다.
- JSDoc이나 임의 타입 흉내보다 데이터 shape를 생성 함수와 상수 정의로 명확히 유지한다.
- 새 필드를 추가하면 루트 상태 생성, 저장/로드, 렌더링 소비 지점을 함께 갱신한다.
- 매직 넘버를 늘리기보다 상수나 계산 유틸로 승격한다.
HTML / CSS 규칙
index.html은 매우 얇게 유지한다.- 스크립트와 스타일 연결은 상대 경로를 유지한다.
- 접근성 속성은 현재 패턴을 따른다. 예:
aria-live,aria-label,role="dialog",aria-modal="true". - 새 마운트 루트나 복잡한 부트스트랩 코드는 만들지 않는다.
- 테마 값은
:root커스텀 프로퍼티에 추가한다. - 색상, radius, shadow, safe-area 값은 하드코딩보다 변수 재사용을 우선한다.
- 클래스명과
data-action은 의미 기반 kebab-case를 사용한다. 예:phone-frame,section-card,toast-stack. - 레이아웃은 Flex와 Grid를 혼합하는 현재 방식을 유지한다.
- 반응형은 명시적 미디어 쿼리로 처리한다. 현재 기준점은
@media (max-width: 399px). - 모션은
reduce-motion클래스에서 한꺼번에 죽일 수 있게 설계한다. - 색상 스킴은
only light로 고정되어 있으므로 임의 다크 모드 추가는 기본 가정이 아니다. - 사용자에게 보이는 텍스트는 한국어를 우선한다.
문서와 UX 일관성
README.md와docs/는 기능 의도와 UX 방향의 근거 문서다.- 구현이 문서와 충돌하면 먼저 현재 코드와 README를 기준으로 맞추고, 필요하면 문서도 같이 갱신한다.
- 작은 화면 대응, 세로 모드, 한 손 조작, 빠른 루프는 계속 우선순위가 높다.
새 기능 추가 체크리스트
- 홈/게임/업그레이드/결과/설정 중 영향 받는 화면을 모두 확인했는가?
stateshape 변경이 저장/로드/Hydrate에 반영되었는가?dispatchAction()와 해당data-action버튼이 연결되었는가?- 토스트, 튜토리얼, 작은 화면 레이아웃까지 확인했는가?
- README나 docs를 함께 갱신해야 하는 변경인가?
하지 말아야 할 것
- 근거 없이 프레임워크, 빌드 도구, 상태 라이브러리를 추가하지 말 것.
- 기존
innerHTML렌더링 패턴과 섞이는 부분 리액티브 패턴을 임의 도입하지 말 것. - 영어 UI 텍스트로 전체 톤을 깨지 말 것.
- 모바일 우선 레이아웃을 해치는 데스크톱 전용 구조를 기본값으로 만들지 말 것.
- 테스트 명령이 없다고 검증을 생략하지 말 것. 반드시 수동 검증 절차를 남길 것.