ソース情報
- リポジトリ
- DevooKim/my-gallery
- ソースの最終更新活動
- 2026年7月6日 14:04
- 検出された SKILL.md の言語
- 韓国語
- スター
- 3
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/DevooKim/my-gallery --skill verifyコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SOC 職業分類に基づく
SKILL.md を表示中
| name | verify |
| description | 3D 갤러리 앱을 실행하고 브라우저로 전체 관람 플로우(입장→이동→감상→복귀)를 검증하는 레시피 |
npm run dev # 기본 5173 포트, 백그라운드 실행
Chrome DevTools MCP로 접속.
콘솔에서 import('/src/store.ts')는 앱과 다른 모듈 인스턴스를 만든다 — HMR을 거친 앱 그래프는 ?t=타임스탬프가 붙은 URL을 쓰기 때문. 앱 스토어를 진단하려면 변환된 소스에서 실제 URL을 추출해 import하라: const url = (await fetch('/src/ui/Hud.tsx').then(r=>r.text())).match(/"([^"]*store\.ts[^"]*)"/)[1]. 이걸 모르면 "스토어가 안 바뀐다"는 가짜 진단이 나온다.
initScript에서 document.documentElement에 MutationObserver를 붙이면 조용히 실패한다 (그 시점엔 documentElement가 없음). DOMContentLoaded 이후 document.body에 붙일 것.
로딩 진행률 검증: 로컬 자산은 순식간이라 문구가 안 보인다. emulate로 Slow 3G + exhibitions.json 포스터를 임시로 큰 원격 URL(picsum)로 바꿔 검증 후 원복.
포인터 락 요청은 브라우저 창이 OS 포커스를 가질 때만 성공한다. CDP 클릭이 락을 못 걸고 콘솔에 Unable to use Pointer Lock API가 찍히면 select_page를 bringToFront: true로 호출한 뒤 다시 클릭하라. 그래도 불안정하면 아래 락 스텁을 써라.
스크린샷 캡처는 실제 포인터 락을 강제로 풀어버린다 (일시정지 트리거와 동일). 실제 락으로 테스트할 때는 조작→상태확인(evaluate)→스크린샷 순서를 지켜라.
락 스텁: 앱 상태 머신만 검증할 때는 실제 락 대신 주입한다. 스크린샷이 락을 깨는 문제도 사라진다.
let fakeLock = null
Object.defineProperty(Document.prototype, 'pointerLockElement', { configurable: true, get: () => fakeLock })
window.__setLock = (on) => { fakeLock = on ? document.querySelector('canvas') : null; document.dispatchEvent(new Event('pointerlockchange')) }
키 입력: window.dispatchEvent(new KeyboardEvent('keydown', {code:'KeyW'})) 후 setTimeout으로 홀드, keyup으로 종료. 이동 속도 3m/s. 락(또는 스텁)이 켜져 있어야 이동한다.
감상 진입/종료 클릭: canvas.dispatchEvent(new MouseEvent('click', {bubbles:true})) — isTrusted 체크 없음.
캔버스 CDP 클릭: 캔버스는 a11y 트리에 없으므로 canvas.setAttribute('role','button') + aria-label 후 snapshot→click.
canvas.__r3f 없음). Player가 포인터 모드에서 매 프레임 Raycaster.setFromCamera(coords, camera)를 호출하므로, 앱과 같은 three 모듈 인스턴스의 프로토타입을 훅하면 카메라를 얻는다 (점프 y 궤적·yaw 측정에 사용; 터치 모드는 탭 시점에만 레이캐스트하므로 매 프레임 샘플이 없다):
const threeUrl = (await fetch('/src/scene/Player.tsx').then(r=>r.text())).match(/import \* as THREE from "([^"]+)"/)[1]
const THREE = await import(threeUrl)
const orig = THREE.Raycaster.prototype.setFromCamera
THREE.Raycaster.prototype.setFromCamera = function (c, cam) { window.__cam = cam; return orig.call(this, c, cam) }
document.pointerLockElement !== null (스텁 사용 시 스텁 값)합성 mousemove는 Chrome에서 movementX를 지원하므로 회전을 실제로 검증할 수 있다:
const moveMouse = (dx) => document.dispatchEvent(new MouseEvent('mousemove', { movementX: dx, movementY: 0, bubbles: true }))
파랑새 앞에서 조준 힌트가 켜진 상태를 기준으로:
moveMouse(40) ×20) → 힌트 꺼짐 (회전 동작 확인)하나라도 실패하면 락 상태가 어딘가에 복제/캐시되고 있다는 뜻이다. CLAUDE.md 금지 목록 참조.
window.matchMedia = (q) => q === '(pointer: coarse)' ? { matches: true, media: q, addEventListener(){}, removeEventListener(){}, ... } : orig(q). inputMode는 마운트 시 1회 판정.style.touchAction === 'none' && style.inset === '0px'인 div)에 합성 PointerEvent(pointerType 'touch') dispatch:
THREE.Clock: This module has been deprecated — R3F 내부, 무시.