From agentic-development-workflow
Reference for AEP's git worktree workflow: branch naming, one-commit-per-task rule, recovery via reflog, and PR conventions used by /aep-launch, /aep-build, and /aep-wrap.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agentic-development-workflow:git-refThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`/aep-launch`, `/aep-build`, and `/aep-wrap` operate on a plain git repository plus `git worktree` for parallel agent isolation. There is no separate VCS, no colocated mode, no special wrapper — when these skills say "commit", they mean `git commit`. This skill documents the AEP-specific conventions on top of standard git.
/aep-launch, /aep-build, and /aep-wrap operate on a plain git repository plus git worktree for parallel agent isolation. There is no separate VCS, no colocated mode, no special wrapper — when these skills say "commit", they mean git commit. This skill documents the AEP-specific conventions on top of standard git.
If you've used git for ten minutes, you already know 90% of this. The remaining 10% is the conventions AEP layers on top.
AEP previously used Jujutsu (jj) in colocated mode for change-mutability and zero-disk workspaces. We migrated to pure git because:
git status reflexively, and on a colocated jj+git repo that returned confusing detached-HEAD output.gh, IDE git panes, every CI provider, husky hooks — all assume git. jj needed adapter skills.git commit per task is now enforced upfront.What we lost: jj's auto-rebase, conflict-as-data, and op log recovery. The replacements (linear commits, eager conflict resolution, git reflog) are documented below.
See docs/decisions/migrate-from-jj-to-git.md for the full rationale.
Every AEP git operation targets the integration branch — the branch feature worktrees are
created from, rebased onto, PR'd into, merged into, and where control-plane commits (/aep-dispatch,
/aep-design, the /aep-wrap archive) land. Throughout this skill and the bash blocks in /aep-launch,
/aep-build, /aep-wrap, and the product-context skills, this branch is referred to as $BASE.
AEP auto-detects one of two modes — no configuration required for the common cases:
| Mode | Condition | Integration ($BASE) | Production |
|---|---|---|---|
| single-branch (default) | no develop branch | main | main (same branch) |
| two-branch | develop exists | develop (staging) | main (promote-only) |
A project grows from single- to two-branch mode simply by creating a develop branch — no
reconfiguration. In two-branch mode AEP never touches the production branch (main): promotion
from integration to production (develop → main) is the user's concern, exactly like deployment,
which is already outside AEP's scope.
$BASEEvery git-touching skill resolves the integration branch at the top of its first bash block:
# Resolve AEP integration branch ($BASE): override → auto-detect develop → main
BASE=$(git config --get aep.integration-branch 2>/dev/null || true)
if [ -z "$BASE" ]; then
if git show-ref --verify --quiet refs/heads/develop \
|| git show-ref --verify --quiet refs/remotes/origin/develop; then
BASE=develop
else
BASE=main
fi
fi
Resolution order:
git config --get aep.integration-branch. This is an override only,
for a non-standard integration branch name (e.g. staging, integration). You do not set it
for the standard main/develop cases — those are auto-detected. /aep-onboard reports the detected
mode and only writes this key when you use a non-standard name.develop if it exists locally or on origin.main (single-branch mode).Because the standard cases are auto-detected (not pinned), a project grows from single- to
two-branch mode with no reconfiguration: create develop and every skill resolves $BASE to it
on the next run. (If you had pinned aep.integration-branch=main, that override would win and
suppress the upgrade — which is why setup does not pin the default.)
git config --get aep.integration-branch is repo-local and shared across all worktrees via the
common .git/config, so $BASE resolves identically in the main session and inside any
.feature-workspaces/<name> worktree.
# Resolve $BASE — see "Integration Branch" above (override → develop → main)
BASE=$(git config --get aep.integration-branch 2>/dev/null || true)
[ -z "$BASE" ] && { git show-ref --verify --quiet refs/heads/develop \
|| git show-ref --verify --quiet refs/remotes/origin/develop; } && BASE=develop
BASE=${BASE:-main}
mkdir -p .feature-workspaces
git worktree add -b feat/<name> .feature-workspaces/<name> "$BASE"
.feature-workspaces/<name> (kept gitignored).feat/<name> — corresponding to the OpenSpec change name or story id.$BASE — never another feature branch.The worktree shares .git/objects with the main repo, so creating it is fast and history is not duplicated. Only the working tree files are duplicated on disk.
git worktree list # all worktrees, branches, paths
git -C .feature-workspaces/<name> status # status inside a specific worktree
git -C .feature-workspaces/<name> log --oneline "$BASE"..HEAD # commits unique to the feature branch
/aep-wrap step 6)git worktree remove .feature-workspaces/<name>
git branch -d feat/<name>
If git branch -d warns the branch isn't fully merged (likely because the PR was squash-merged so commit SHAs differ), force with git branch -D feat/<name> after confirming via gh pr view <number> --json state that the PR is MERGED.
If .feature-workspaces/<name>/ was deleted manually:
git worktree prune # forget the orphaned registration
git branch -D feat/<name> # delete the orphan branch (if needed)
If .git/worktrees/<name>/ still references a missing path (e.g. you moved the parent directory):
git worktree repair .feature-workspaces/<name>
| Branch | Pattern | Created by |
|---|---|---|
| Feature work | feat/<short-name> | /aep-launch (one per story) |
| Migration / chore | chore/<short-name> | manually, when applicable |
| Hotfix off main | fix/<short-name> | manually |
| Migration project | migration/<topic> | manually |
Rules:
git worktree prune cleans up dangling refs)./aep-build)This is the largest AEP-specific convention.
tasks.md lists N tasks. The feature branch ends up with N commits — one per task — in the same order. Conventional-commit format. Workspace agents implement linearly, committing after each task, never bundling and never splitting:
# Implement task 1
# ... edit files ...
git add -A
git commit -m "feat(auth): extract auth service"
# Implement task 2
# ... edit files ...
git add -A
git commit -m "feat(auth): add token refresh flow"
# ... etc.
After each commit, record the short SHA in .dev-workflow/feature-verification.json against the matching task entry's commit_sha field.
tasks.md.git show <sha> independently.| Situation | Action |
|---|---|
| Forgot a file in the just-committed task | git add <file> && git commit --amend --no-edit (only safe before the next task's commit) |
| Realized the previous task is broken, several commits ago | Add a new commit: fix(<scope>): correct <issue from task N> — do not rebase |
| Review feedback or eval-loop FAIL | Add a follow-up commit: fix(<scope>): address review on <topic> |
Need to update against new origin/$BASE | git fetch origin && git rebase origin/"$BASE" && git push --force-with-lease origin feat/<name> |
| Conflicts during rebase | Resolve in working tree, git add <files> && git rebase --continue. If hopelessly tangled, git rebase --abort and surface to the orchestrator via signal file. |
Never use git push --force (without --force-with-lease). The lease variant fails safely when someone else has pushed since your last fetch.
# First push (after Phase 9 cleanup):
git push -u origin feat/<name>
# Subsequent pushes (review fixes, rebases):
git push origin feat/<name>
# or after a rebase:
git push --force-with-lease origin feat/<name>
# $BASE is the integration branch — resolve it first (see "Integration Branch" above)
gh pr create --base "$BASE" --title "<title>" --body "<body>"
The --base "$BASE" flag is mandatory. Without it, gh infers the base from local branch state and can target the wrong branch (especially when a dispatch commit looked like a recent base). PRs targeting the wrong base merge into a non-integration branch, and the code never lands on the integration branch even after a successful merge. In two-branch mode this is doubly important — an inferred base could be production main, which AEP must never merge feature work into directly.
gh pr merge <number> --squash --delete-branch
We always squash-merge. The feature branch's per-task commits collapse into one commit on the integration branch ($BASE), which keeps its log readable while preserving the per-task review trail in the PR's "Commits" tab.
/aep-dispatch, /aep-envision, /aep-map, /aep-calibrate, /aep-validate, /aep-reflect, and the /aep-wrap archive step all commit directly to the integration branch ($BASE). The pattern is identical:
# Resolve $BASE — see "Integration Branch" above (override → develop → main)
BASE=$(git config --get aep.integration-branch 2>/dev/null || true)
[ -z "$BASE" ] && { git show-ref --verify --quiet refs/heads/develop \
|| git show-ref --verify --quiet refs/remotes/origin/develop; } && BASE=develop
BASE=${BASE:-main}
git pull --ff-only origin "$BASE" # fail-fast if the integration branch has diverged
git add <specific-files> # never -A on the integration branch; be explicit
git commit -m "<conventional message>"
git push origin "$BASE"
The --ff-only is intentional — it refuses a non-fast-forward pull, which means concurrent pushes get caught instead of silently merged. If the pull fails because someone else pushed first, fetch, rebase your work, and try again.
git reflog # find the orphaned commit's SHA
git cherry-pick <sha> # bring it onto the current branch
# or
git reset --hard <sha> # if you want to rewind to that point
git reflog # the deleted branch's tip is in here
git branch <name> <sha> # recreate the branch at that tip
If you ran rm -rf .feature-workspaces/<name> without committing first, the work is gone — git worktree only tracks committed history. .dev-workflow/ files (signals, lessons, progress) are also gone since they're gitignored. Use git worktree remove instead of rm -rf next time; it refuses if the worktree has uncommitted changes.
If the dispatch commit's OpenSpec files disappeared during a rebase or merge:
git log --oneline -n 30 # find the dispatch commit SHA
git restore --source=<sha> -- openspec/
This restores openspec/ to the state of the dispatch commit without touching anything else.
Each worktree adds approximately one full working-tree copy on disk. .git/objects is shared across all worktrees, so commit history isn't duplicated. For a typical AEP repo (~100 MB working tree, multi-GB .git/objects after years of history), three concurrent agents adds ~300 MB on top of one shared .git/.
Monitor with:
du -sh .feature-workspaces/ # working-tree footprint
du -sh .git/objects # shared history
If disk pressure hits before agents finish, prefer pausing new /aep-launch invocations over forcibly removing in-flight worktrees.
| You want to… | Run |
|---|---|
| Create a feature worktree | git worktree add -b feat/<n> .feature-workspaces/<n> "$BASE" |
| List all worktrees | git worktree list |
| See feature-branch commits | git log --oneline "$BASE"..HEAD |
Sync against latest $BASE | git fetch origin && git rebase origin/"$BASE" |
| Push after rebase | git push --force-with-lease origin feat/<n> |
| Open PR | gh pr create --base "$BASE" |
| Merge PR | gh pr merge <#> --squash --delete-branch |
| Remove worktree post-merge | git worktree remove .feature-workspaces/<n> && git branch -d feat/<n> |
| Recover deleted commit | git reflog then git cherry-pick <sha> |
| Restore lost openspec/ files | git restore --source=<sha> -- openspec/ |
npx claudepluginhub memorysaver/agentic-engineering-patterns --plugin agentic-development-workflowProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.