Verify Finite
Finite는 두 가지 표면을 가지며, 대부분의 기능은 두 표면이 모두 필요합니다. 에이전트는 /mcp의 MCP 도구(doc6 6개 도구; call은 /mcp/classic의 클래식 도구를 구동)를 통해 디자인을 편집합니다. 사용자는 브라우저에서 확인합니다: 디자인 목록(/)과 캔버스(/design/?id=<designId>). 증명은 call로 에이전트 측을 구동하고 페이지에서 사용자 측을 확인하거나, 댓글의 경우 반대로 진행합니다.
하네스는 e2e/headless.mjs입니다. .agents/skills/finite-headless/SKILL.md는 이 하네스의 명령 참조서입니다(섀도우 루트, 샌드박스 iframe, --agent, Python에 접근하는 선택자 포함). 첫 번째 구동 전에 한 번 읽어보세요. 이 스킬은 격리, 닥터, 증거 폴더, 전후 실행 및 기능 맵을 추가합니다.
아래 모든 명령은 체크아웃 루트에서 실행합니다:
V=.agents/skills/verify-finite/scripts/verify.sh
셸 변수는 도구 호출 간에 유지되지 않습니다. 각 호출 시작 부분에 V=...와 RUN=...을 반복하세요.
단계
- 기능 선택. 변경 사항이 영향을 미치는 기능을
features/README.md의 "변경 사항이 영향을 미치는 기능" 테이블에서 찾습니다. - 실행 코드의 실행을 시작합니다. 버그 수정의 경우 수정 전 코드의 실행도 함께 시작합니다("전후 비교" 참조).
- 닥터 각 실행이
ok줄만 출력할 때까지 검사합니다. - 구동 선택한 각 기능 파일의 모든 진입점을 구동하면서 증거를 저장합니다.
- 정리 시작한 모든 실행(실패한 실행 포함)을 정리합니다.
- 보고 "보고" 형식에 따라 보고합니다.
선택한 모든 기능의 모든 진입점이 증명되었거나, 이유와 함께 건너뛰어졌거나, 증거와 함께 실패했으며, $V list에 실행 중인 항목이 없으면 완료됩니다.
실행
$V launch # 서버, finite.wasm, 웹 앱을 빌드한 후 시작
$V launch --no-build # 마지막 빌드 재사용; 빌드 이후 코드 변경 시 거부
$V launch --width 390 --height 844 # 모바일 크기 페이지 (기본값 1440 × 900)
$V launch --at main # 다른 커밋 실행, 임시 체크아웃에서 ("전후 비교" 참조)
RUN=<run>을 출력합니다. 이 id를 유지하세요: 다른 모든 명령이 이 id를 사용합니다. 콜드 빌드는 약 2분, 할 일이 없는 빌드는 몇 초가 걸립니다. Bash 타임아웃을 600000으로 설정하세요. --no-build는 할 일이 없는 빌드의 몇 초만 절약하므로, 의심스러우면 사용하지 않는 것이 좋습니다.
Finite at http://127.0.0.1:<port>가 출력되면 실행 준비가 완료된 것입니다. 하네스는 /api/health를 기다리고 해당 줄이 출력되기 전에 디자인 목록을 로드합니다. 데이터 폴더는 비어 있는 상태로 시작하며 시드 데이터, 마이그레이션 또는 로그인이 없습니다. 사용자는 "Guest"로 댓글을 작성하고, 에이전트는 --agent <name>을 전달하지 않는 한 "Agent"로 작성합니다.
각 실행은 고유한 포트, 임시 데이터 폴더 및 Chrome 프로필을 가진 별도의 세션(verify-<run>)이므로 실행을 나란히 실행할 수 있습니다. 직접 시작하지 않은 Finite는 절대 구동하지 마세요. vp run dev는 crates/server/data의 사용자 실제 디자인을 제공하며, 데스크탑 앱도 사용자 자신의 데이터를 제공합니다. 닥터는 다른 사람의 서버에 연결된 세션에서 실패합니다.
실행은 30분 동안 유휴 상태이면 자동으로 중지됩니다. 이후 doctor는 실패합니다: 정리하고 다시 실행하세요.
닥터
$V doctor $RUN
상태만 읽으며, 모든 줄이 ok 또는 FAIL을 출력합니다. 다섯 가지를 확인합니다:
- 세션이 활성 상태이고 전용
finite-headless-data-*폴더를 소유하고 있습니다. /api/health가package.json의 버전과 함께ok를 응답합니다.- 실행 중인 빌드가 코드와 일치합니다. 빌드 입력(
crates/,apps/web/, 하네스, 잠금 파일, 추적되지 않은 파일 포함)의 해시를 실행이 빌드된 코드의 해시와 비교합니다. 문서, 스킬 또는 테스트 편집은 무시됩니다. get_screenshot을 위한 Chrome, Chromium 또는 Edge가 있습니다.- 페이지가 응답합니다.
그런 다음 마지막 호출 이후의 페이지 콘솔을 출력합니다. 먼저 실행하고, 예상치 못한 상황 후, 최종 증거를 캡처하기 전에 실행하세요. FAIL이 발생하면 계속 구동하지 말고 정리하고 다시 실행하세요. 코드를 변경한 후에는 빌드 확인이 설계상 실패합니다: 정리하고 다시 실행하세요.
구동
$V h $RUN <command> ...는 이 실행에 대해 e2e/headless.mjs 명령을 실행합니다. 가장 많이 사용할 명령:
$V h $RUN call create_design '{"name":"Verify"}' # 에이전트 측: designId "<id>" 출력
$V h $RUN call create_artboard @input.json # JSON 인라인, @file, 또는 - (stdin)
$V h $RUN design <designId> # 사용자 측: 캔버스 열기, 아트보드 대기
$V h $RUN snapshot --selector main # 접근성 트리, 사용자가 보는 내용
$V h $RUN click 'button[title="Comment (C)"]'
$V h $RUN click '[data-artboard] >>> h1' --shift # Shift-클릭
$V h $RUN upload 'input[type=file]' card.html # 파일 선택, OS 선택기처럼
$V h $RUN api GET /api/designs/<designId> # 저장된 디자인, 댓글 포함
이러한 안정적인 핸들을 사용하세요. 앱의 접근 가능한 이름과 제목입니다:
| 위치 | 핸들 |
|---|---|
| 디자인 목록 | 제목 Designs, 버튼 New design, 검색창 Search designs by name, 각 디자인 카드당 하나의 link |
| 캔버스 상단 바 | 링크 ← Designs, button[title="CSS variables every artboard uses, in each mode"] (토큰), button[title="Every comment, open and resolved"] (댓글, 열린 개수가 이름에 포함), Import, Export, 각 에이전트당 칩 |
| 캔버스 도구 | 도구 모음 Tools: button[title="Pointer (V)"], button[title="Comment (C)"]; 키 v, c, Shift+1 (맞춤), =/- (줌) |
| 댓글 상자 | 텍스트 상자 Add a comment, button[title="Change your name"], [data-selection-count], 버튼 Send, 핀 이름 Comment: <first message> |
| 댓글 스레드 | [role=dialog] 이름 Comment thread: 버튼 Delete, Resolve/Reopen, Close, Edit (가장 최근 메시지), 텍스트 상자 Reply |
| 패널 | aside[aria-label=Comments] 탭 Open N / Resolved N; section[aria-label=Tokens] form[aria-label="Add a token"]; nav[aria-label=Pages]; [role=menu][aria-label=Export]; aside[aria-label=Import] status |
| 아트보드 내용 | [data-artboard="<artboardId>"] >>> <css>; 에이전트의 data-name 속성은 DOM에 유지 |
좌표보다는 이들을 선호하세요. 좌표는 선택자가 도달할 수 없는 샌드박스(스크립트) 아트보드에만 사용됩니다. click은 CSS(텍스트 아님)를 사용하므로 제목이 없는 버튼은 위치로 선택합니다: [role=dialog] button --nth 1, query로 순서를 확인합니다.
텍스트 입력에는 두 가지 함정이 있습니다. type은 필드에 있는 내용에 추가하며, key Meta+a는 CDP를 통해 텍스트를 선택하지 않습니다. 필드의 텍스트를 바꾸려면 필드에 포커스가 있는 상태에서 $V h $RUN eval "document.execCommand('selectAll')"를 실행한 다음 type을 사용하세요.
백그라운드 호출
wait_for_comments는 사용자가 댓글을 작성할 때까지 차단되므로 페이지를 구동하는 동안 실행되어야 합니다:
$V bg $RUN 02-wait call wait_for_comments '{"designId":"<D>","timeoutSeconds":30}'
# ...페이지 구동...
$V await $RUN 02-wait 30 # 호출이 반환될 때까지 차단된 후 .verify/<run>/02-wait.txt 출력
await로 결과를 읽고, 파일을 직접 읽지 마세요: 파일은 호출이 반환된 후에만 나타납니다. 백그라운드 호출은 도구 호출 간에 유지됩니다.
증거
모든 내용은 체크아웃의 .verify/<run>/에 저장됩니다. .gitignore가 포함하며 정리 시 보관됩니다.
$V save $RUN 01-comment-posted snapshot --selector main # 명령, 출력 및 종료 코드
$V shot $RUN 02-canvas # .verify/<run>/02-canvas.png
$V shot $RUN 03-panel --selector 'aside[aria-label=Comments]'
save는 모든 헤드리스 명령(call 포함)을 받아 명령, 출력 및 [exit N]을 포함하는 <name>.txt를 작성합니다. 이름에 번호를 매겨 실행 순서대로 읽히도록 하세요. 각 PNG는 의존하기 전에 Read 도구로 읽으세요. get_screenshot 이미지와 경로 없이 찍은 모든 페이지 스크린샷은 세션의 임시 폴더에 저장됩니다. 정리 시 .verify/<run>/tool-images/로 복사하고, 서버 로그는 .verify/<run>/server.log로 복사됩니다. 테스트 입력으로 만든 파일(예: 가져올 파일)도 .verify/<run>/에 저장됩니다.
증명은 다음 기준을 충족해야 합니다:
- 실제 경로. 사용자의 작업은 페이지(클릭, 키, 입력, 업로드)를 통해 이루어지고, 에이전트의 작업은 MCP
call을 통해 이루어집니다. REST API는 저장된 상태를 읽는 데만 사용하세요. 이를 통해 쓰면 증명하려는 UI를 건너뛰게 됩니다. - 작업과 결과. 작업을 수행하는 단계와 그 이후의 상태를 저장하고, 최종 스크린샷만 저장하지 마세요.
- 부작용. 변경 사항이 저장된 것과 표시된 것 모두를 보여주세요.
api GET /api/designs/<id>는 서버가 저장한meta,nodes,comments를 반환하며, 에이전트의 읽기 도구(get_comments,get_tokens,get_tree_summary)는 다음 에이전트가 볼 내용을 보여줍니다. - 실시간 기능의 양방향. 에이전트의 편집은 새로고침 없이 페이지에 나타나야 합니다. 사용자의 댓글은 대기 중인 에이전트에 도달해야 합니다.
- 모의 객체 없음. 실행은 실제 서버, 실제 브라우저 및 실제 MCP 세션을 사용합니다.
- 깨끗한 콘솔.
$V save $RUN <n>-console console으로 마무리하세요. 예외나 실패한 요청이 있으면 증명이 무효화됩니다.
전후 비교
버그 수정은 동일한 과정이 이전 코드에서는 실패하고 새 코드에서는 성공할 때 증명됩니다. 두 실행을 나란히 실행하세요:
$V launch --at main # RUN=<before>: main의 임시 체크아웃, 설치 및 빌드 (약 1분)
$V launch # RUN=<after>: 현재 체크아웃
동일한 증거 이름으로 두 실행에서 동일한 단계를 구동하세요. 이전 실행은 버그를 보여주어야 합니다. 그렇지 않으면 과정이 버그에 도달하지 못한 것이며, 이후 실행은 수정에 대해 아무것도 증명하지 않습니다. --at는 모든 git ref(브랜치, 태그, 커밋, 수정 사항이 아직 커밋되지 않은 경우 HEAD)를 받습니다. 닥터는 실행이 빌드된 ref와 커밋을 명시합니다. 정리 시 임시 체크아웃을 제거하고 증거는 보관합니다.
정리
$V cleanup $RUN
이 실행의 데몬을 중지합니다. 데몬은 자신이 생성한 서버(SIGTERM, 디자인이 먼저 저장됨)와 시작한 Chrome을 중지한 후, 그들의 임시 데이터와 프로필을 삭제합니다. 그런 다음 정리 시 서버 로그와 도구 이미지를 증거 폴더로 복사하고, --at 실행의 임시 체크아웃을 제거하며, 보관한 항목을 나열합니다. 다른 세션, vp run dev 및 데스크탑 앱은 계속 실행되도록 그대로 둡니다.
$V list는 현재 체크아웃에서 여전히 실행 중이거나 체크아웃이 남아 있는 실행을 출력합니다. 각 실행을 $V cleanup <run>으로 정리하고, pkill을 사용하지 마세요. $V prune [days]는 정리된 실행 중 해당 일수(기본값 7일)보다 오래된 증거를 삭제합니다. 보고할 증거가 있는 실행은 절대 정리하지 마세요.
보고
구동한 각 기능에 대해 하나의 블록으로 마무리하세요:
<기능 ID> via <진입점>: proven | skipped | failed
evidence: .verify/<run>/<files>
why (skipped or failed): <실행한 명령과 누락되거나 잘못된 내용>
그런 다음 실행 id, 각 실행에 대한 닥터의 출력, 그리고 수정의 경우 버그를 보여주는 이전 실행의 증거를 제공하세요. 다른 진입점이 동일한 동작을 증명했더라도 건너뛴 진입점은 skipped로 보고하세요.
도우미
scripts/verify.sh는 다음 명령을 받습니다: launch, doctor, h, save, shot, bg, await, cleanup, list, prune. 인수 없이 실행하면 인수 목록을 확인할 수 있습니다. e2e/headless.mjs의 얇은 래퍼입니다: 세션은 verify-<run>, 증거는 .verify/<run>/에 저장됩니다.