Handles scenario creation + execution + auto-correction in a single loop. References existing scenario code patterns and, when needed, inspects the DOM in real time to write scenarios. On execution failure, analyzes the error and directly modifies the script to re-execute.
Mode
| Mode | Trigger | Action |
|---|---|---|
auto (default) |
/peach-e2e-scenario [설명] |
Create + execute + auto-correct loop |
create |
/peach-e2e-scenario create [설명 or codegen] |
Create scenario only |
run |
/peach-e2e-scenario run [경로 or 번호] |
Execute + auto-correct loop |
Tool role division
| Purpose | Tool |
|---|---|
| Run scenario | ./e2e.sh run (playwright-cli based) |
| Selector debugging/DOM inspection | agent-browser eval (fast) |
| iframe debugging | ./e2e/pwc.sh eval (fallback) |
| Syntax validation | node --check |
Force gate
- For launching Chrome Beta,
cd e2e && ./e2e.sh chromeis used preferentially. If direct execution is needed,--user-data-dir=$HOME/.chrome-beta-e2e-profilemust be included. ./e2e.sh statusCheck the tab list with , and before the user specifies the execution tab,./e2e.sh run,agent-browser eval, do not start tab switching.- For tasks where Google login, OAuth, admin console, payment, or maintaining the existing Chrome Beta profile session is essential, proceed only up to scenario creation/analysis, and start actual execution after user confirmation.
agent-browserIf debugging is abnormal, do not bypass the browser at the OS level (open -a, launching another browser, using another profile path).- If login/two-factor authentication is required, do not handle it directly by AI; guide the user to complete authentication first in the fixed Chrome Beta profile.
Chrome Beta launch invariant rules
When launching Chrome Beta in CDP mode, the fixed profile option is mandatory. A launch missing the profile option is considered a session maintenance failure.
- Allowed:
cd e2e && ./e2e.sh chrome - Required options for direct execution:
--remote-debugging-port=9222,--remote-allow-origins=*,--user-data-dir=$HOME/.chrome-beta-e2e-profile,--disable-extensions - macOS direct execution standard:
/usr/bin/open -na "Google Chrome Beta" --args ... - Prohibited:
open -a "Google Chrome Beta"standalone launch,--argswithoutopenlaunch,--user-data-dirChrome Beta launch without , arbitrary use of other profile paths, bypassing with default Chrome or another browser
Workflow
Common: environment check + tab check
cd e2e && ./e2e.sh setup
setupAutomatically checks/installs all of these environments (Chrome Beta, agent-browser, playwright-cli, CDP connection).
If CDP is not connected, first attempt automatic recovery in the following order.
cd e2e && ./e2e.sh chrome &executionsleep 4waitcd e2e && ./e2e.sh statusrecheck- If still not connected, guide the user to
cd e2e && ./e2e.sh chromemanual execution
./e2e.sh chromeuses the fixed profile ($HOME/.chrome-beta-e2e-profile) is the standard path for launching Chrome Beta. Instead of this command, even when launching Chrome directly,--user-data-dirdo not omit the option.
cd e2e && ./e2e.sh status
Show the tab list to the user and "Which tab number should it run in?" confirm.
Tab numbers start from 0.
chrome://tabs are excluded.[번호]가--tab NSame as N in. Use the tab the user is logged into as is. No distinction between environments (local/test/prod). Do not execute before receiving a tab number. For sensitive session operations, even after receiving a tab number, only perform analysis until user approval. Tab drift prevention: after the user responds with a tab number,agent-browser tab Nimmediately afteragent-browser eval "document.title + ' | ' + location.href"re-verify that the tab is correct. If it differs from expected,./e2e.sh statusre-output and reselect. For debugging/reproduction,E2E_TAB_IDfixing is recommended. (Details:peach-e2e-browse/references/탭-선택-패턴.md)
File upload scenario: if in the scenario code
page.setInputFiles()or file input manipulation is needed, To block the OS native file dialog,Page.setInterceptFileChooserDialoguse the method. CDP Escape /agent-browser press Escapecannot close the macOS native dialog. (Details:peach-e2e-browse/references/SPA-프레임워크-입력패턴.md §3)
auto mode (default)
- Input source determination — natural language request vs codegen recorded code
- Reference existing scenario patterns —
e2e/시나리오/read existing code under to identify patternsreferences/시나리오-생성-패턴.mdReference
- DOM pre-inspection (if needed) — pre-check URL structure and selectors with agent-browser eval
- Scenario generation —
references/코드패턴.mdwrite the script by referencing- If codegen input,
references/변환규칙.mdadditionally reference - For differences by framework,
references/프레임워크-대응.mdreference
- If codegen input,
- Check information — scenario name (Korean), save category folder (Korean business domain), sequence within category (
NN-), the state contract this scenario leaves behind, the prerequisite state contract this scenario requires - Syntax validation —
node --checkconfirm passing - Confirm execution approval
- Normal screen: after checking the tab number and scenario path, execute
- Google/OAuth/admin/payment/existing Chrome Beta profile session retention tasks:
./e2e.sh runbefore execution, always re-confirm actual execution approval with the user
- Execution —
./e2e.sh run --tab N 시나리오/경로 - Auto-fix loop — on failure, below auto-fix loop proceed
- Report results
create mode
- Input source determination
- Natural language request →
references/시나리오-생성-패턴.md+references/코드패턴.mdreference - codegen recording →
references/변환규칙.md+references/코드패턴.mdreference
- Natural language request →
- Check information — scenario name (Korean), save category folder (Korean business domain), sequence within category (
NN-), the state contract this scenario leaves behind, the prerequisite state contract this scenario requires - Scenario creation
- Required conversion items (when codegen input):
chromium.launch()→connect()(using lib/connect.js)page.goto('/path')→ Check current tab state, then conditionally navigate- Do not auto-navigate if the session is sensitive or there is no user approval
- Only when the session is non-sensitive + user approval is obtained
page.goto()
browser.close()/context.close()removalpage.pause()removal- Add dialog handler (
setDialogHandlerreplacement + restoration in finally is required) - Wrap with try-catch-finally + exitCode pattern (
process.exit(0)fixed termination prohibited) - Add emoji logs
waitForTimeoutminimize → convert to conditional wait- Popup (
waitForEvent('popup')) → detect closing withwaitForEvent('close')use
- Required conversion items (when codegen input):
- Syntax validation —
node --checkconfirm passing - Save report —
e2e/시나리오/{한글카테고리}/{NN}-{시나리오명}.js- Auto-create category folder if it does not exist
- Do not immediately bulk-move existing flat-structure files; migrate gradually to the new rules only at the time of modification/rewriting
- When migrating, specify the existing path and new path in the completion report
run mode
- Scenario selection
cd e2e && ./e2e.sh list - Execution approval confirmation
- Scenarios whose core requirement is maintaining a logged-in real tab/fixed profile session require user approval before execution
- Execution
cd e2e && ./e2e.sh run --tab N 시나리오/경로 - Auto-fix loop — on failure, the following Auto-fix loop proceed
- Result report
Auto-fix loop (up to 3 times)
If the scenario execution result is ❌ 에러:then directly modify the script and re-execute.
It is this skill's responsibility not to stop at simple debugging guidance, but to identify the cause, fix the scenario file, and re-execute it.
If a selector/DOM/framework interaction issue is suspected during auto-fixing,
peach-e2e-browseapply the decision tree of to re-check the DOM and interaction method in the current tab.
Reflect the confirmed selectors and event patterns in the scenario code, then re-execute.
Details: references/자동수정-판단트리.md reference
Judgment criteria
| Error type | Handling method |
|---|---|
| Selector mismatch (timeout, locator not found) | Check the actual DOM with agent-browser eval → fix the scenario selector |
dialog auto-close (기록하지 못했습니다, dismiss) |
Check for daemon remnants, then kill → setDialogHandler if the pattern is not applied, fix it |
popup waitForEvent('close') error |
Promise.race + .catch(() => {}) apply pattern |
URL pattern mismatch (waitForURL timeout) |
Check the actual navigation URL → fix the pattern |
Timing issue (waitForTimeout immediate failure after) |
Fixed wait → waitForEvent or waitForFunction Replace with event-based |
Target page, context or browser has been closed |
Popup/tab closed earlier than expected → .catch(() => {}) or closeTarget Add option |
| navigation timeout (AJAX submit) | Remove waitForNavigation or replace with waitForURL |
| Server error (500, network error) | Cannot auto-fix → Report to user and stop |
Loop procedure
1. 에러 메시지 파싱 → 유형 판별
2. agent-browser eval로 실제 DOM/URL 확인
3. 시나리오 스크립트 수정
4. 재실행
5. 여전히 실패? → 1로 돌아감 (최대 3회)
6. 3회 실패 → 진단 패키지 출력 → 사용자에게 보고 → peach-e2e-browse 안내
Output diagnostic package after 3 failures
If all 3 auto-fix attempts fail, anchoring (accumulated incorrect-answer bias) riskincreases. Do not forcibly increase to 4 or 5 attempts in the same context; debug with a clean context in a new conversation windowso that it can be done, output a structured diagnostic package.
Output format
🩺 자동수정 3회 실패 — 진단 패키지
## 시나리오
- 파일: <시나리오 파일 절대경로>
- 대상 URL: <실행 대상 URL>
- 탭 ID: <E2E_TAB_ID>
## 시도 이력 (3회)
| 회차 | 추정 원인 | 적용한 수정 | 재실행 결과 |
|------|----------|------------|-----------|
| 1 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
| 2 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
| 3 | <유형> | <변경 요약> | <에러 메시지 첫 줄> |
## 마지막 실패 컨텍스트
- 마지막 에러 메시지 (전문)
- 실패 시점 DOM 스냅샷 또는 셀렉터 평가 결과
- 실패 시점 URL
## 추정 막힌 지점
<3회 모두 같은 유형이면 그 유형, 다르면 "다중 원인 의심" 명시>
## 사용자 다음 액션 가이드
1. 새 대화창에서 위 패키지를 첨부하여 디버깅 진행
2. peach-e2e-browse로 현재 탭 상태 직접 확인
3. 시나리오 의도 자체 재검토 필요 가능성
Principles
- so that the context can be started anew Include all absolute paths, full errors, and the entire attempt history inline (no summarizing)
- Do not automatically expand to 4 or 5 attempts (Bounded Autonomy: May Suggest area, user decides)
- If the user wants to continue in the same session, make additional attempts, but warn once about the anchoring riskdo so
Re-run after fixing
E2E_TAB_ID=<id> ./e2e.sh run '시나리오/대상.js'
If it is a dialog-related error, always check for lingering daemons before execution:
lsof -iTCP:9222 -sTCP:ESTABLISHED -n -P | awk '/node/{print $2}' | xargs kill -9 2>/dev/null
Selector debugging (prefer agent-browser eval)
# CDP 연결 (1회)
agent-browser connect 9222
# 현재 URL 확인
agent-browser eval "location.href"
# 셀렉터 존재 여부
agent-browser eval "document.querySelector('.target') !== null"
# 버튼 목록
agent-browser eval "JSON.stringify(Array.from(document.querySelectorAll('button')).map(function(b){return b.innerText}))"
# 요소 개수
agent-browser eval "document.querySelectorAll('tr').length"
Debugging inside an iframe is not possible with agent-browser → playwright-cli fallback:
./e2e/pwc.sh eval "document.querySelector('iframe[src*=target]').contentDocument.querySelector('#element').innerText"
Native dialog scenario rules
window.alert/confirmJS monkey-patch는 does not work — Playwright CDP auto-dismiss runs first. Do not use.- Native dialog handling must always use CDP layer handler (
page.on('dialog', handler)) use. connect.js의setDialogHandler(page, prevHandler, newHandler)Replace the handler with the utility, and always restore it in finally. Multiplepage.on('dialog')If registered, all are executed and a conflict ("already handled") occurs — the replacement pattern is mandatory.- popup(
waitForEvent('popup'))은connect.jsis not passed through, so a separate handler must be registered. process.exit(0)Do not use fixed termination →try/catch/finally + exitCodeuse the pattern.- For page-state-dependent logic, explicitly wait before clicking.
- For dialog waiting, instead of a fixed
waitForTimeoutinsteadpage.waitForEvent('dialog')use event-based.
Details: peach-e2e-browse/references/native-dialog-주의사항.md reference
External service switching
Entering external sites (Google, Gmail, etc.) uses the load + 2초 지연 + 직접 이동 fallback pattern.
Details: peach-e2e-browse/references/외부서비스-링크전환-패턴.md reference
Tab selection rules
- Normal execution:
--tab N(for fast execution) - Debugging/reproduction/failure analysis:
E2E_TAB_IDpreferred (prevents index drift)
# targetId 조회
curl -s http://127.0.0.1:9222/json | jq -r '.[] | select(.type=="page" and (.url|startswith("chrome")|not)) | [.id,.title,.url] | @tsv'
# targetId로 실행
cd e2e && E2E_TAB_ID=<targetId> ./e2e.sh run '시나리오/대상.js'
Details: peach-e2e-browse/references/탭-선택-패턴.md reference
Unit vs integration responsibility boundary
- Unit scenario (peach-e2e-scenario): Verify that the behavior of one screen/one action is correct. Prepare its own starting data, run independently, reusable.
- Integration suite (peach-e2e-suite): Combine multiple units into business lifecycle units to verify that the user flow runs all the way to the end. Do not modify unit .js files.
If the same flow repeats across units, express it as a combined integration suite.
Unit Scenario Authoring Principles
A unit scenario is a reusable component that can be combined in a suite. Follow these principles.
- Single Responsibility: Verify only one screen or one business action. Do not bundle two or more core flows into one scenario.
- Prepare Start Data Yourself: Do not "assume existing data is present." The scenario itself creates the required starting state (or receives it as explicit input).
- Independent Execution: Do not depend on the execution results of other scenarios. It produces the same result regardless of execution order.
- Reusable: Write it so that the unit .js can be used as-is in a suite without modification. If there are values to be injected externally, receive them as explicit input (environment variables/state.json).
- Failure Isolation: Even if one unit fails, it does not affect the execution of other units. Specify cleanup responsibility.
Scenario Design Principles
Unit Separation Criteria (Reuse Units)
Divide unit scenarios according to the following criteria.
- Separate into business transaction unitsthat leave behind state for the next step to reuse.
- Example: input complete, processing complete, result confirmation. Leave meaningful state for the next scenario in state.json or environment variables.
- Do not over-separate into single click/input units.
- Separate repeated technical functions such as login, search, and repeated clicks into helpers, not scenarios .Separate repeated technical functions such as login, search, and repeated clicks into helpers, not scenarios.
The save path follows the e2e/시나리오/{한글카테고리}/{NN}-{시나리오명}.js format.
Details: peach-e2e-suite/references/suite-scenario-파일구조.md See reference
E2E_BASE Pattern (Domain Environment Variable)
Use the E2E_BASE environment variable pattern at the very top of every scenario file. Hardcoding the domain is an anti-pattern that blocks multi-environment execution.
// 시나리오 파일 최상단 필수
const BASE = process.env.E2E_BASE || 'http://local.example.com';
When running:
# 로컬 (기본값)
./e2e.sh run --tab N 시나리오/경로.js
# 개발서버 지정
E2E_BASE=https://dev.example.com ./e2e.sh run --tab N 시나리오/경로.js
DB-free Design (Role Separation Principle)
Scenario .js files handle only UI manipulation and UI result verification . Since DB access itself is structurally impossible, within the scenario do not attempt either reads or writes.
- Structural Constraint: Because the NODE_PATH of the e2e.sh execution environment does not include the mysql/postgres client, DB libraries (
mysql,dbQuery등)requirethemselves fail with ENOENT in the scenario. If DB connection information enters the scenario, environment portability also becomes zero. - Therefore, all operations that require a DB are separated outside the scenario(suite fixture Step,
peach-db-query(skills, admin screen actions, TDD API). - If a request for a scenario that violates the above boundary is received (e.g., "In this scenario, INSERT to create the precondition"), immediately notify the user, first propose one of the bypass paths below, then obtain consent.
| Purpose | Attempt within the scenario (not possible) | Bypass path |
|---|---|---|
| PK extraction | SELECT pk FROM table WHERE name='...' |
Admin list DOM input.pk_check[request_name] attribute |
| Save verification | SELECT column FROM table WHERE pk=N |
After screen reload, input element .value check |
| DB precondition | INSERT INTO ... |
suite fixture Step or peach-db-query skill |
| Force state transition | UPDATE ... SET status=... |
Add suite fixture Step or admin screen action to the scenario |
| Clean up residual data | DELETE FROM ... |
suite fixture Step or hardDelete TDD API call |
| DB consistency check | — | suite MD "DB verification (optional)" section + peach-db-query skill (SELECT) |
PK extraction standard pattern
Standard pattern for extracting the PK from the admin list DOM after registration:
await page.evaluate((name) => { $('#page_keyword').val(name); searchFormSubmit(); }, TEST_NAME);
await page.waitForTimeout(1500);
const N = await page.evaluate((name) => {
const el = document.getElementById('list_inner_html') || document.body;
const cb = el.querySelector(`input.pk_check[request_name="${name}"]`);
return cb ? parseInt(cb.value, 10) : null;
}, TEST_NAME);
if (!N || N <= 0) throw new Error('PK 추출 실패');
Prerequisite: in the admin list, input.pk_check there is a checkbox, and request_name attribute contains the name, valuecontains the PK.
Core principles
- Always
lib/connect.js의connect()use the function - Execution must always
node—bunis unable to connect to CDP WebSocket - Understand the DOM structure of the target project and apply an appropriate selector strategy
- Modal handling: refer to per-framework patterns (iframe vs Portal/Teleport)
- Install dialog handler conditionally, not globally
- For switching to external service links,
click()apply the fallback URL reachability rule rather than a single line - Immediately after saving,
node --checkSyntax verification is required using - In states with unconfirmed tabs and sensitive session operations, perform analysis only and proceed with execution after user confirmation
Reference documents
| Document | Purpose | Load condition |
|---|---|---|
references/코드패턴.md |
Basic scenario structure (IIFE, exitCode, emoji) | create, auto |
references/변환규칙.md |
codegen → CDP conversion rules | When codegen is input |
references/프레임워크-대응.md |
Legacy/modern framework branching | create, auto |
references/시나리오-생성-패턴.md |
Generation guide based on existing code references | create, auto |
references/validation-통과-패턴.md |
form validation bypass pattern | create, auto |
references/자동수정-판단트리.md |
Auto-fix strategy per error type | On run, auto failure |
references/daemon-잔류-대응.md |
CDP daemon troubleshooting | On dialog error |
references/dialog-handler-패턴.md |
Native dialog handling mechanism | dialog scenario |