베이스 업데이트와 도입
라이선시 fork는 한 번 받고 끝이 아닙니다. 베이스(ddakit/e2e-base)가 새 스킬을 추가하거나 훅을 고치거나 AI_AUTOMATION.md를 갱신할 때마다 그 변경이 fork에 도달해야 라이선스 가치가 유지됩니다. /update-from-base가 git rebase 모르고도 안전하게 받게 해주고, 이미 테스트가 있는 외부 프로젝트는 /adopt가 베이스 패턴에 맞춥니다.
/update-from-base 영역별 owner
섹션 제목: “/update-from-base 영역별 owner”업데이트가 무엇을 덮어쓰고 무엇을 그대로 두는지는 파일 자리로 결정됩니다. 자동 갱신, 절대 안 건드림, 사람이 결정. 이 셋의 분기가 핵심입니다.
base-owned 자동 갱신 대상
섹션 제목: “base-owned 자동 갱신 대상”베이스가 SSOT인 자리입니다. 사용자가 편집해도 다음 update에서 베이스 버전으로 돌아갑니다.
| 경로 | 무엇 |
|---|---|
.claude/skills/{base-skill}/ | 베이스 스킬 정의 (phase 1~6, implement-*, review-e2e, run-suite 등) |
.claude/agents/*.md | 베이스 agent 정의 (e2e-architect, e2e-builder, e2e-reviewer) |
.claude/hooks/*.sh + README | 베이스 훅 (session-start, stop-reminder, pre-commit-check) |
.claude/settings.json | 베이스 훅 등록 |
AI_AUTOMATION.md | 도메인 SSOT |
베이스 스킬 본문은 직접 고치지 않는 게 원칙입니다. 자기 스킬을 추가하고 싶으면 별도 디렉토리(예: .claude/skills/my-team-<name>/)에 만듭니다. 같은 trigger 키워드를 가진 자기 스킬을 두면 베이스가 그 키워드의 스킬을 갱신해도 자기 쪽은 살아남습니다.
user-owned 절대 안 건드림
섹션 제목: “user-owned 절대 안 건드림”| 경로 | 무엇 |
|---|---|
tests/ | 사용자가 작성한 테스트 전부 (POM, fixtures, specs, flows) |
playwright.config.ts, .detoxrc.js, .maestro/, .github/workflows/e2e.yml | 트랙 config와 CI |
.env.test.example, .env.test.local | 테스트 환경변수 |
docs/design/e2e-spec.md | 사용자가 작성한 테스트 사양 |
docs/adr/*.md (README.md 제외) | 사용자 결정 기록 |
.claude/state/*, .claude/session-state/*, .claude/agent-memory/* | 런타임, 세션, 메모리 |
LICENSE, COMMERCIAL-LICENSE.md | 라이선스 |
.github/workflows/e2e.yml이 user-owned인 점을 짚어둡니다. CI 워크플로는 implement-ci-workflow가 만들지만 사용자 SUT에 맞춰 손볼 수 있는 자리라, 베이스가 워크플로 패턴을 바꿔도 자동으로 덮지 않습니다. 라이선스 파일도 베이스가 갱신하면 안내만 띄우고 사용자가 수동 결정합니다.
mixed 3-way 안내
섹션 제목: “mixed 3-way 안내”CLAUDE.md, README.md, AGENTS.md 셋입니다. 베이스와 사용자 양쪽 편집이 동시에 들어갈 수 있어 자동 갱신하지 않고 diff만 보여주고 묻습니다. 베이스 버전으로 통째 덮기, 베이스 변경분만 3-way merge, 미루기. 셋 중 하나를 고릅니다.
한 사이클
섹션 제목: “한 사이클”/update-from-base 또는 “베이스 업데이트 받아줘”라고 부르면 다음을 거칩니다.
git remote add base https://github.com/ddakit/e2e-base.git # 처음 한 번git fetch base maingit diff --name-status <last_synced_commit>..base/main # 영역별 분류.claude/state/base-upstream.json의last_synced_commit을 baseline으로 변경분을 영역별로 나눕니다.- dirty working tree면
git stash를 권합니다. - base-owned 변경을 한 줄씩 요약합니다. 새 스킬 N개, 갱신된 훅 M개,
AI_AUTOMATION.md갱신 여부. - 사용자 yes 시
git checkout base/main -- .claude/skills/ .claude/agents/ .claude/hooks/ .claude/settings.json AI_AUTOMATION.md. - mixed 파일은 한 개씩 옵션을 골라 적용합니다.
- 적용 후
.sh에chmod +x,settings.jsonJSON 파싱, 새 스킬의 trigger 키워드를 나열합니다. base-upstream.json을 새 hash로 갱신하고 commit을 권합니다.
기본 흐름은 대개 30초에서 2분 사이로 끝납니다. mixed 파일 결정에서만 시간이 더 걸립니다.
last_synced_commit이 base/main 히스토리에 더 이상 없으면(베이스가 force-push 한 경우) 도구는 자동 적용을 멈추고 안내만 띄웁니다. 일반 케이스가 아닙니다.
왜 자동 적용이 아니라 영역 분류인가
섹션 제목: “왜 자동 적용이 아니라 영역 분류인가”가장 단순한 설계는 git pull base main 한 줄입니다. 그렇게 하지 않은 이유는 둘입니다. git pull은 베이스 변경과 사용자 변경을 같은 레이어로 보고 merge commit과 그 뒤의 충돌 해결을 만듭니다. 비개발자에게 그 자리가 그대로 막힙니다. 그리고 base-owned 영역만 “베이스가 SSOT”라는 합의가 있어서 그 자리만 자동으로 덮는 게 안전합니다. 합의가 없는 mixed는 사람이 결정하게 둡니다.
/adopt 이미 e2e가 있는 앱에 얹기
섹션 제목: “/adopt 이미 e2e가 있는 앱에 얹기”새로 시작하는 게 아니라 이미 Playwright나 Maestro 테스트가 일부 있는 외부 repo를 베이스 패턴에 맞추고 싶을 때 /adopt를 씁니다. /e2e-stage-detect가 “뭐가 있나”를 본다면 /adopt는 “있는 게 베이스 스킬과 동작하나”를 봅니다. 자동 마이그레이션이 아니라 우선순위 매긴 plan을 만들고, 적용은 항목별 확인 후입니다(S5).
다섯 영역을 점검합니다.
| 영역 | 보는 자리 | 호환 기준 |
|---|---|---|
| 도구 | Playwright/Cypress/Detox/Maestro 설치와 설정 | Playwright나 Maestro/Detox면 baseline 호환. Cypress, Selenium은 마이그레이션 plan |
| 디렉토리 구조 | tests/<track>/{pages,fixtures,specs} POM+fixtures 형태인가 | 로케이터 인라인이면 POM 분리 plan |
| 인증 전략 | 매 테스트 UI 로그인 vs 세션 재사용 | 재사용 없으면 implement-auth-fixtures 적용 plan |
| CI | .github/workflows/의 e2e 잡 형태 | 브라우저 캐싱, xvfb 누락 등을 기준과 비교 |
| state/docs | e2e-suite-config.json, e2e-spec.md 유무 | 없으면 /3-analyze-target과 /4-design-suite로 역으로 채우기 |
각 항목을 호환, LOW, HIGH, BLOCKING으로 등급합니다. 번들러나 런타임이 베이스 가정과 크게 다르거나 기존 테스트가 프로덕션 SUT를 친다면 BLOCKING으로 표시하고, 그 경우 새로 시작 옵션을 제시합니다. Cypress 같은 다른 프레임워크는 전면 재작성을 강요하지 않고 “유지 후 점진 마이그레이션”도 옵션으로 둡니다.
인접 자리
섹션 제목: “인접 자리”- 비개발자 호흡으로 같은 절차를 따라가는 자리는 비개발자용 staying-up-to-date에 있습니다.
- 이 스킬이 라이선스 모델의 안전망인 이유는 intro의 무오염 원칙과 라이선스 단락 옆에 두고 봅니다.