Skip to content

Base Updates and Adoption

A licensee fork is not a one-time grab. Every time the base (ddakit/e2e-base) adds a skill, fixes a hook, or updates AI_AUTOMATION.md, that change has to reach the fork for the license to keep its value. /update-from-base lets you receive it safely without knowing git rebase, and for an external project that already has tests, /adopt aligns it with the base pattern.

What an update overwrites and what it leaves alone is decided by file location. Auto-update, never touched, human-decided. That three-way split is the core.

Seats where the base is the SSOT. Edit them and the next update reverts to the base version.

PathWhat
.claude/skills/{base-skill}/Base skill definitions (phase 1 through 6, implement-*, review-e2e, run-suite, etc.)
.claude/agents/*.mdBase agent definitions (e2e-architect, e2e-builder, e2e-reviewer)
.claude/hooks/*.sh + READMEBase hooks (session-start, stop-reminder, pre-commit-check)
.claude/settings.jsonBase hook registration
AI_AUTOMATION.mdDomain SSOT

The rule is not to edit base skill bodies directly. To add your own skill, make it in a separate directory (for example .claude/skills/my-team-<name>/). Keep your own skill on the same trigger keyword and your side survives even when the base updates the skill for that keyword.

PathWhat
tests/Everything the user wrote (POM, fixtures, specs, flows)
playwright.config.ts, .detoxrc.js, .maestro/, .github/workflows/e2e.ymlTrack config and CI
.env.test.example, .env.test.localTest env vars
docs/design/e2e-spec.mdThe test spec the user wrote
docs/adr/*.md (except README.md)User decision records
.claude/state/*, .claude/session-state/*, .claude/agent-memory/*Runtime, session, memory
LICENSE, COMMERCIAL-LICENSE.mdLicense

Worth flagging that .github/workflows/e2e.yml is user-owned. The CI workflow is generated by implement-ci-workflow, but it is a spot the user can tune to their own SUT, so it is not overwritten automatically even when the base changes the workflow pattern. License files, when the base updates them, only surface a notice and the user decides manually.

Three files: CLAUDE.md, README.md, AGENTS.md. Both base and user edits can land at once, so they are not auto-updated — the diff is shown and you are asked. Overwrite wholesale with the base version, 3-way merge just the base changes, or defer. Pick one of the three.

Call /update-from-base (or “pull the base update”) and it goes through this.

Terminal window
git remote add base https://github.com/ddakit/e2e-base.git # first time only
git fetch base main
git diff --name-status <last_synced_commit>..base/main # per-area classification
  1. Using last_synced_commit in .claude/state/base-upstream.json as the baseline, it splits the changes by area.
  2. On a dirty working tree it suggests git stash.
  3. It summarizes the base-owned changes one line each. N new skills, M updated hooks, whether AI_AUTOMATION.md changed.
  4. On a user yes: git checkout base/main -- .claude/skills/ .claude/agents/ .claude/hooks/ .claude/settings.json AI_AUTOMATION.md.
  5. Mixed files get an option picked and applied one at a time.
  6. After applying, it chmod +xs the .sh files, parses settings.json as JSON, and lists the trigger keywords of any new skill.
  7. It updates base-upstream.json to the new hash and suggests a commit.

The default flow usually finishes in 30 seconds to 2 minutes. Only the mixed-file decisions take longer.

If last_synced_commit is no longer in the base/main history (the base force-pushed), the tool stops auto-applying and only surfaces a notice. Not the common case.

Why area classification instead of auto-apply

Section titled “Why area classification instead of auto-apply”

The simplest design is one line, git pull base main. Two reasons it is not done that way. git pull treats base changes and user changes as the same layer and creates a merge commit and the conflict resolution that follows. That spot stalls a non-developer outright. And only the base-owned area carries the agreement that “the base is the SSOT,” so it is safe to auto-overwrite only there. Mixed, where there is no such agreement, is left for a human to decide.

/adopt, laying it onto an app that already has e2e

Section titled “/adopt, laying it onto an app that already has e2e”

When you are not starting fresh but want to align an external repo that already has some Playwright or Maestro tests to the base pattern, use /adopt. Where /e2e-stage-detect asks “what is here,” /adopt asks “does what is here work with the base skills.” It is not an auto-migration — it builds a prioritized plan, and applying it is per-item confirmed (S5).

It checks five areas.

AreaWhat it looks atCompatibility bar
ToolPlaywright/Cypress/Detox/Maestro install and configPlaywright or Maestro/Detox is baseline-compatible. Cypress, Selenium get a migration plan
Directory structureIs it in tests/<track>/{pages,fixtures,specs} POM+fixtures shapeInline locators get a POM-separation plan
Auth strategyUI login every test vs session reuseNo reuse gets an implement-auth-fixtures plan
CIThe e2e job shape in .github/workflows/Compares browser caching, missing xvfb, etc. against the bar
state/docsWhether e2e-suite-config.json and e2e-spec.md existIf absent, backfill with /3-analyze-target and /4-design-suite

Each item is graded compatible, LOW, HIGH, or BLOCKING. If the bundler or runtime differs sharply from the base assumptions, or existing tests hit a production SUT, it is marked BLOCKING and a start-fresh option is offered for that case. A different framework like Cypress is not forced into a full rewrite — “keep it and migrate gradually” stays on the table as an option.

  • The same procedure at a non-developer pace lives in the beginner staying-up-to-date.
  • Why this skill is the safety net for the license model is best read next to the no-contamination rule and the license paragraph in the intro.