
Aep Build
- 50 installs
- 14 repo stars
- Updated July 31, 2026
- memorysaver/agentic-engineering-patterns
Helps with ai & agent building tasks.
About
aep-build is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- aep-build
- AI & Agent Building
- AI-coding skill
Aep Build by the numbers
- 50 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #7,298 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/memorysaver/agentic-engineering-patterns --skill aep-buildAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 50 |
|---|---|
| repo stars | ★ 14 |
| Last updated | July 31, 2026 |
| Repository | memorysaver/agentic-engineering-patterns ↗ |
What it does
Helps with ai & agent building tasks.
Files
Build
Autonomous feature implementation inside an isolated git worktree on a fresh feat/<name> branch. Initialize the harness, implement tasks linearly (one commit per tasks.md row), review, test, create a PR, handle feedback, and merge — all without user interaction.
Phase numbering note: Phases 1-3 (explore, propose, review) were completed on main via /aep-design. This skill begins at Phase 0 (workspace init) and continues from Phase 4 (implementation).Loop hygiene (G7): Each phase runs under a unified --max-turns runaway budget. Hitting the cap is not completion — treat it as "possibly unsolvable → escalate" (Human-Gate Protocol, distinct from a genuine clean finish). This keeps a stuck phase (e.g. a non-converging Phase 5 loop) from silently burning turns and reading as done.Where this fits:
/aep-onboard → /aep-scaffold → [ /aep-design → /aep-launch → /aep-build → /aep-wrap ]
▲ you are hereSession: Workspace session, autonomous Input: OpenSpec artifacts on disk (committed to main by /aep-design) Output: Merged PR
---
Phase 0: Initialize Tracking
Before any work begins, set up the tracking infrastructure and environment. The branch is already created by /aep-launch (feat/<name>); you do not pre-create commits — implement linearly in Phase 4.
1. Read the worktree-onboarding guide at skills/agentic-development-workflow/build/references/worktree-onboarding.md.
2. Discover the OpenSpec change:
- List
openspec/changes/to find the active change - Read all artifacts:
proposal.md,design.md,specs/**/*.md,tasks.md
3. Create the tracking folder:
mkdir -p .dev-workflow4. Add `.dev-workflow/` to `.gitignore` if not already present:
grep -q '.dev-workflow' .gitignore || echo '\n# Development workflow tracking (per-workspace)\n.dev-workflow/' >> .gitignore5. Create the progress file from the template:
cp skills/agentic-development-workflow/build/references/progress-template.md \
.dev-workflow/progress-$(git rev-parse --short HEAD).mdFill in feature name, base commit SHA, date, and OpenSpec change name. Mark design phases as pre-completed (they were done on main via /aep-design).
6. Read tasks.md to understand the task list:
cat openspec/changes/<change-name>/tasks.mdtasks.md _is_ the skeleton. You will implement tasks linearly in Phase 4, committing once per task with conventional-commit messages — the resulting commit history will mirror the task list 1:1.
7. Run project setup (if a setup hook exists):
SETUP_HOOK=.claude/hooks/workspace-setup.sh
if [ -f "$SETUP_HOOK" ]; then
bash "$SETUP_HOOK"
else
echo "No workspace setup hook found at $SETUP_HOOK"
echo "Read the project README or ask the user for setup instructions."
fiThe project's setup hook handles all project-specific concerns:
- Package installation (bun/npm/pnpm/cargo/poetry/etc.)
- Dev server startup
- Port assignment → writes
.dev-workflow/ports.env - Database migrations, seeding
- Docker/container management
.envfile validation
Contract: The hook MUST write .dev-workflow/ports.env with at minimum:
WEB_PORT=<port>
SERVER_PORT=<port>
BASE_URL=http://localhost:<web-port>
SERVER_URL=http://localhost:<server-port>If no hook exists and no README provides instructions, ask the user how to set up the project.
8. Generate sprint contracts:
Read specs/*.md, design.md, and tasks.md. For each task, generate a contract entry in .dev-workflow/contracts.md using the template at references/contract-template.md:
## Task: <task-description>
**Source spec:** <matching spec file>
### What will be built
- [specific files/components]
### Success criteria
- [extracted from matching spec]
### Verification steps
1. [concrete, executable step]
2. [what to check]9. Generate feature verification list:
Extract the verification steps from contracts into .dev-workflow/feature-verification.json:
[
{
"task": "<task description>",
"commit_sha": null,
"verification_steps": ["step 1", "step 2", "step 3"],
"passes": false,
"evaluated_by": null,
"round": null
}
]commit_sha starts as null and is filled in (8-char prefix) after each task is committed in Phase 4.
Rules:
- JSON format is intentional — models tamper with JSON less than Markdown
- The generator agent MUST NOT modify
verification_stepsorpasses— only the evaluator (or human) does
10. Generate session recovery script:
Create .dev-workflow/init.sh for resuming after context resets:
#!/bin/bash
# Session recovery script — run this to resume after context reset
set -e
cd "$(dirname "$0")/.."
# Project setup (deps, dev server, ports)
SETUP_HOOK=.claude/hooks/workspace-setup.sh
if [ -f "$SETUP_HOOK" ]; then
bash "$SETUP_HOOK"
else
echo "No workspace setup hook found. Check project README for setup instructions."
fi
# Source ports (written by setup hook)
source .dev-workflow/ports.env 2>/dev/null
# Current state
echo "=== Branch & Commits ==="
echo "Branch: $(git branch --show-current)"
git log --oneline "$(git config --get aep.integration-branch 2>/dev/null || (git show-ref --verify --quiet refs/remotes/origin/develop && echo develop || echo main))"..HEAD 2>/dev/null || git log --oneline -10
echo "=== Progress ==="
grep '\[x\]' .dev-workflow/progress-*.md 2>/dev/null | tail -10
echo "=== Next Phase ==="
grep '\[ \]' .dev-workflow/progress-*.md 2>/dev/null | head -3Make executable: chmod +x .dev-workflow/init.sh
11. Initialize inter-agent signals:
mkdir -p .dev-workflow/signalsCreate .dev-workflow/signals/status.json:
{
"phase": 0,
"phase_name": "initializing",
"task_current": null,
"task_index": 0,
"task_total": 0,
"started_at": "<ISO 8601 timestamp>",
"blockers": [],
"completion_pct": 0,
"last_updated": "<ISO 8601 timestamp>",
"story_status": "in_progress",
"pr_url": null,
"cost_usd": null,
"completed_at": null,
"failure_log": null,
"blocked_on": null
}Check for feedback from main session:
cat .dev-workflow/signals/feedback.md 2>/dev/nullSee skills/agentic-development-workflow/launch/references/signals-spec.md for the full signal file specification.
12. Create the lessons file:
cat > .dev-workflow/lessons.md <<'TEMPLATE'
# Lessons: <change-name>
Module: <module>
Activity: <activity>
Date: <date>
Story: <story-id>
## Solutions
## Errors
## Missing
## Summary for Next Agent
TEMPLATEThis file captures what the agent learns during builds — solutions discovered, errors encountered, missing docs, patterns that worked. Fill in the header fields from the OpenSpec change. Sections are populated during Phase 4 (opt-in) and Phase 9 (summary).
Update the Phase 0 checkbox in the progress file when done.
Signal update: Update.dev-workflow/signals/status.jsonwith"phase": 0, "phase_name": "initialized", "completion_pct": 10.
---
Story Status Tracking (Product-Cycle Mode Only)
Standalone mode: Ifproduct-context.yamldoesn't exist, skip this entire section. Signal updates (status.json) still work — just omitstory_statusfields.
If this feature corresponds to a story in product-context.yaml (check if the OpenSpec change name matches a story's openspec_change field):
Build-Time Dependency Re-Verification (Phase 0)
Before starting implementation, re-verify that all dependencies are still completed:
Read product-context.yaml (READ-ONLY — workspace agents never write to this file)
Find this story by openspec_change match
For each dependency in story.dependencies:
If dependency.status != completed:
ABORT build
Signal via .dev-workflow/signals/status.json:
{ "phase": 0, "phase_name": "dependency_check_failed",
"blockers": ["<dep_id> is not completed"] }
Stop and wait for main session to investigateAlso check dispatched_at_epoch vs current dispatch_epoch. If the epoch advanced since dispatch, re-read the YAML to check for architecture amendments.
Why: A dependency could be rolled back after dispatch (e.g., PR reverted). This defense-in-depth catches issues that dispatch-time checks missed.
Status Updates via Signals
CONCURRENCY PROTOCOL: Only the main session writes toproduct-context.yaml. Workspace agents report status through.dev-workflow/signals/status.json. The main session (via/aep-wrap,/aep-dispatch) reads signals and updates the YAML.
All story status updates flow through the signal file, NOT direct YAML writes:
- Phase 0 start: Confirm story status is
in_progressin the YAML (read-only check) - Phase 10 (PR created): Update
status.jsonwithstory_status: "in_review"andpr_url - Phase 12 merge: Update
status.jsonwithstory_status: "completed",completed_at,pr_url,cost_usd - On failure (escalation): Update
status.jsonwithstory_status: "failed"andfailure_log(structured record: error_class, approach_summary, unexplored_alternatives)
/aep-wrap (running on main) reads these signal fields and writes the final status to product-context.yaml.
If product-context.yaml doesn't exist, skip this tracking (standalone feature mode).
---
Phase 4: OpenSpec Apply
Implement each task in tasks.md linearly. After each task, commit with a conventional-commit message and record the resulting commit SHA in feature-verification.json:
# For each task in tasks.md, in order:
# ... implement the task — edit files directly ...
git status # Inspect changes
git diff # Verify the change matches the task
# ... run targeted tests for this task ...
git add -A
git commit -m "feat(<scope>): <task description>"
# Record the commit SHA in feature-verification.json:
SHA=$(git rev-parse --short HEAD)
# Update the matching task entry's commit_sha field with $SHA
# (use jq or a small inline script — never modify verification_steps or passes)Invoke the apply skill for guidance on implementing each task:
/opsx:applyThe agent works one task at a time. Each task = one commit. The branch's commit history mirrors tasks.md 1:1, which makes per-task code review on the PR straightforward.
UI-facing stories — obey the Object Map. If the dispatched context package
includes an Object Map slice (objects, attributes, relationships, CTAs, screens),
treat it as binding structure: build the listed screens object-first (noun→verb —
object collection/detail, the given CTA placements), use the specified core
attributes, and do not introduce objects/screens outside the slice or collapse
a flow into a step-by-step wizard unless the slice marks it task_oriented.Visual look (calibration/visual-design.yaml), copy voice (copy-tone), and
journey/transition (ux-flow) still govern taste — the Object Map governs objectstructure and CTA grammar.
Update the progress file checkbox for each completed task, and mark the Phase 4 checkbox when all tasks are done.
If you need to amend a just-committed task (e.g., you forgot a file), use git commit --amend --no-edit _before_ moving on. Once you've committed the next task, leave prior commits alone — fixes belong as a follow-up commit, not a rewrite.Lesson capture (opt-in per task): After completing each task, if you encountered something noteworthy — a non-obvious solution, an error that took multiple attempts, missing documentation — append to .dev-workflow/lessons.md under the appropriate section (## Solutions, ## Errors, or ## Missing). Use a ### <title> sub-heading with a brief explanation. This is not mandatory for every task — only write when something is genuinely worth passing on to the next agent.
Signal update: Update.dev-workflow/signals/status.jsonwith"phase": 4at start, updatetask_current,task_index,task_totalas tasks progress, andcompletion_pctproportionally.
---
Phase 5: Code Review & Verification
After implementation, verify the code before moving to testing. This phase uses the generator/evaluator pattern — read the shared utility for full details:
- Scoring framework:
.claude/skills/aep-gen-eval/references/scoring-framework.md(dimensions, thresholds, presets) - Agent contracts:
.claude/skills/aep-gen-eval/references/agent-contracts.md(role separation, prompt templates) - Eval protocol:
.claude/skills/aep-gen-eval/references/eval-protocol.md(request/response format, verification JSON, convergence rules)
Completeness check (always done by generator)
1. Re-read the proposal (including any design review adjustments) 2. Walk through each task's commit, reviewing with git show <commit-sha> against its task description 3. Check .dev-workflow/contracts.md — verify each task's success criteria are met 4. If any task is incomplete, add a follow-up commit (feat(<scope>): complete <task> or fix(<scope>): <issue>) and loop back to Phase 4. Do not rewrite prior commits.
Quality review
With separate evaluator (full mode):
If .dev-workflow/evaluator-criteria.md exists (written during /aep-launch), spawn an evaluator via executor.spawn_evaluator(). The generator orchestrates the entire evaluation loop — no manual intervention needed. The spawn mechanism tracks the active executor mode (read .claude/skills/aep-executor/references/backends.md):
| Generator mode | Evaluator spawn (executor.spawn_evaluator) | eval-protocol mechanism |
|---|---|---|
| native-bg-subagent / claude-bg | foreground Task subagent in the generator's own session — inherits the worktree cwd; the evaluator prompt _is_ the spawn prompt | Context B mechanism, worktree-bound — _not_ its read-only /aep-validate use |
| codex-subagent / codex-exec | codex exec --cd <abs worktree> with the aep-evaluator role — enforced cwd, bounded one-shot | Context C mechanism, in-host headless — _not_ API/SDK CI |
| legacy (tmux) | tmux split-window — evaluator in a bottom pane | Context A (tmux split) |
| workflow | the workflow's verify stage (worktree-isolated) | Context C mechanism, in-host — _not_ API/SDK CI |
Always worktree-bound. Whatever the mode, the evaluator runs against this
workspace's worktree (files + git state), per executor.spawn_evaluator().The Context labels name the spawn _mechanism_, not the read-only/CI _use
cases_ those contexts describe in eval-protocol — a Task-subagent evaluator
is not a main-session read-only reviewer, and a codex exec evaluator isnot an API/SDK CI job. It is worktree-bound review.
For the native modes the evaluator prompt is delivered at spawn time — there is no readiness wait, no separate send step, and no pane to kill; the agent/exec returns when eval-response-<N>.md is written. The legacy tmux recipe is shown below for pinned-tmux workspaces; the request/response signal files and convergence rules are identical across modes.
Why tmux splits, not cmux splits (legacy): The generator runs inside tmux but was not spawned by cmux,
so it cannot use cmux socket commands. Use tmux split-window instead — under cmux the surface attachedto the tmux session will display both panes automatically.
Evaluation round
For each round N (starting at 1, max 5), the generator's response to a FAIL escalates along the change-strategy recovery ladder (.claude/skills/aep-gen-eval/references/recovery-ladder.md) rather than retrying the same way every round:
| Eval round | Rung | Generator move |
|---|---|---|
| 1–2 | Same fix | Same generator fixes the FAIL items in place (current default). |
| 3 | Re-ground | Same generator re-reads the FULL spec + design + contracts from scratch, then re-attempts. |
| 4 | Different approach | Spawn a fresh `native-bg-subagent` generator told "the previous approach failed on X; take a different design path" — not anchored on the stuck solution (it inherits the existing worktree). |
| 5 | Decompose | Split the story into sub-tasks; attempt the smallest viable slice and surface the proposed split. |
| after 5 | Human gate | Ladder exhausted → escalate with type eval_not_converging. |
Track the rung with eval_round + recovery_rung in status.json (see the ladder's State Tracking). Generator≠evaluator separation holds — the evaluator only scores; re-grounding, a fresh generator, and decomposition are all generator-side moves. Skip the ladder and escalate immediately on a hard-failure / security FAIL (auth-model gap, data-exposure risk), a spec contradiction, or a missing external dependency — these need human judgment, not a different approach. See the ladder file for full rung rationale and the rung-4 fresh-generator spawn contract (native-bg-subagent + post-spawn liveness probe).
For each round N (starting at 1, max 5):
1. Write eval-request — create .dev-workflow/signals/eval-request.md per the format in eval-protocol.md (Signal Files section).
2. Compose the evaluator prompt from agent-contracts.md (Evaluator Prompt — Code Quality template). Customize with the workspace paths:
EVAL_PROMPT = <evaluator prompt from agent-contracts.md, customized with:
criteria_file=.dev-workflow/evaluator-criteria.md
eval_request_file=.dev-workflow/signals/eval-request.md
spec_directory=openspec/changes/<change-name>/
contracts_file=.dev-workflow/contracts.md
verification_file=.dev-workflow/feature-verification.json
eval_response_file=.dev-workflow/signals/eval-response-<N>.md
>3. Spawn the evaluator (mode-dispatched, prompt = spawn prompt):
- native-bg-subagent / claude-bg: spawn a foreground Task subagent with
EVAL_PROMPT. It inherits the worktree cwd and returns when done — no sleep, no send step, no teardown.
- codex-subagent / codex-exec:
codex exec --cd "$(pwd)" --dangerously-bypass-approvals-and-sandbox \
"$EVAL_PROMPT" < /dev/null(With the aep-evaluator role committed in .codex/agents/, prefer spawn_agent(agent_type: "aep-evaluator", ...) from a living thread.)
- legacy (pinned tmux):
# Split current tmux window vertically (top=generator, bottom=evaluator). The evaluator
# needs to read files and write eval-response, so it runs the INTERACTIVE executor.
tmux split-window -v -c "$(pwd)" "${EXECUTOR:-claude --dangerously-skip-permissions}"
tmux select-pane -t :.0 # return focus to the generator pane
sleep 10
# Multi-line prompt: send literally with -l, then a single Enter.
tmux send-keys -t :.1 -l -- "$EVAL_PROMPT"
tmux send-keys -t :.1 Enter4. Confirm the response exists (the native spawns return on completion; the legacy pane needs a poll):
while [ ! -f .dev-workflow/signals/eval-response-<N>.md ]; do sleep 15; done5. Read the response. Legacy only: close the evaluator pane (tmux kill-pane -t :.1). Native evaluators have already exited.
6. Fix FAIL items per the recovery rung — add follow-up commits addressing each FAIL item, then loop back to step 1 with round N+1. On rounds 1–2 fix in place; on round 3 re-ground (re-read the full spec/design/contracts from scratch first); on round 4 spawn a fresh native-bg-subagent generator with a different approach; on round 5 decompose to the smallest viable slice. Do not rewrite history; the PR review should see the fix as new commits on top. (Hard-failure/security FAILs skip the ladder and escalate immediately — see the rung table above.)
7. Max 5 rounds — once the ladder is exhausted (not converging after round 5), escalate to human via the human-gate protocol (see below) with type eval_not_converging, recording the ladder history. See the convergence rules in eval-protocol.md and recovery-ladder.md.
The evaluator also updates .dev-workflow/feature-verification.json with pass/fail results per the field ownership rules in eval-protocol.md.
Without evaluator (light mode):
Self-review with awareness of its limitations:
1. Correctness — Logic errors, off-by-one bugs, missing edge cases? 2. Security — Input validation, auth checks, SQL parameterization? 3. Performance — N+1 queries, missing indexes, unbounded loops? 4. Conventions — Naming, file structure, error handling, imports?
Note: Self-review tends to be lenient. If using light mode, be extra critical and walk through feature-verification.json steps manually.Document findings in .dev-workflow/code-review-<feature>.md. Fix any issues found.
Update the Phase 5 checkbox in the progress file when complete.
Signal update: Update.dev-workflow/signals/status.jsonwith"phase": 5, "phase_name": "code-review".
The Human-Gate Protocol (any phase)
When you hit a decision only the human can make — design ambiguity the spec doesn't resolve, eval non-convergence after max rounds, a product judgment call — do not guess and do not silently stall. Raise a gate:
1. Record it (always): append to .dev-workflow/signals/needs-human.md:
## <ISO8601> — Phase <N>
**Question:** <the decision needed, with the options you considered>
**Context:** <why you can't decide autonomously>and set "blocked_on": "human" in status.json.
2. Raise it on your mode's transport (how you were launched tells you the mode — see the Human-Gate Protocol in aep-executor/references/backends.md). The answer always comes back through the main agent (hub-and-spoke) — you never need the human to visit your surface:
- codex-subagent: ask the parent thread (approvals surface natively)
- legacy: the file is the transport — the orchestrator detects it and
relays the answer via nudge
- native-bg-subagent / claude-bg / codex-exec / workflow / headless: gate-and-park — no
push channel reaches you, so after recording the gate: commit WIP (or leave the tree clean), update status.json, and end your run cleanly (workflow agents: return a structured gated result carrying the question). The orchestrator will resume a worker into this same worktree with the human's answer — your state is in the worktree + .dev-workflow/, so nothing is lost.
3. Block-in-place modes only: continue what you can that doesn't depend on the answer; otherwise wait, re-checking feedback.md.
4. On answer (delivered by push, or in your resume prompt after a park): append resolved: <summary> under your entry, clear blocked_on, and proceed.
---
Phase 6: Browser Testing (Dogfood)
Light mode: Skip this phase. Otherwise do not skip just because `agent-browser` is absent — pick a host-aware method and degrade (see below).
Pick the method, host-aware. Call dogfood_method() from .claude/skills/aep-executor/references/dogfood-validation.md to select the right native validation tool for this host/mode:
- Claude Code (any mode) —
/agent-browser:dogfoodifagent_browser_healthy(); otherwise degrade (non-UI changes → API/curl checks; UI changes → human-eval) rather than skipping. - Codex — native in-app browser + computer-use (codex-subagent desktop), else a Playwright script (codex-exec headless), falling back to the agent-browser CLI, then API checks.
Target URL stays local. Resolve via target_url(local) from dogfood-validation.md — source .dev-workflow/ports.env and use $BASE_URL:
source .dev-workflow/ports.env # target_url(local) → $BASE_URLIf the selected method is /agent-browser:dogfood, run it against $BASE_URL:
/agent-browser:dogfoodWhatever the method, emit the unified severity/category/repro report format (see dogfood-validation.md → Unified report format) so the downstream classifier stays host-agnostic. Document results in .dev-workflow/dogfood-<feature>.md — write the report file, not just chat output: that path is the ingestion contract (dogfood-validation.md → On issue), so /aep-watch's dogfood_report source can auto-file bug/refinement findings. Findings left only in chat are a dead end.
Signal update: Update.dev-workflow/signals/status.jsonwith"phase": 6, "phase_name": "dogfood-testing".
---
Phase 7: E2E Test Script Generation
Skip if E2E testing is not set up for this project. Light mode: Skip this phase.
Generate a reusable E2E test script if the project has an E2E testing setup. The script should:
- Source
.dev-workflow/ports.envfor dynamic ports - Use
$BASE_URLand$SERVER_URL(never hardcoded ports) - Cover the key user flows from the feature
---
Phase 8: Review Results
Light mode: Skip this phase.
1. Source .dev-workflow/ports.env for correct ports 2. Run any E2E test scripts to verify they pass 3. Present to the user (or note in progress file):
- Code review from Phase 5
- Dogfood report from Phase 6 (if run)
- E2E test results from Phase 7 (if run)
4. If tests fail, loop back to the appropriate phase
Signal update: Update.dev-workflow/signals/status.jsonwith"phase": 8, "phase_name": "review-results".
---
Phase 9: Cleanup & Publish
Note: Do NOT run/opsx:archivehere. Archive runs on the integration branch after merge (via/aep-wrap).
0. Write lesson summary
Before publishing, write a final ## Summary for Next Agent section in .dev-workflow/lessons.md (1-3 sentences): what would you tell the next agent building in this module? If the lessons file has no entries beyond the template header, write the summary anyway — even "straightforward implementation, no surprises" is useful signal.
1. Review the commit history
git log --oneline "$(git config --get aep.integration-branch 2>/dev/null || (git show-ref --verify --quiet refs/remotes/origin/develop && echo develop || echo main))"..HEADThe history should be a clean linear sequence: one commit per tasks.md task, optionally followed by review-fix commits. The PR will be squash-merged on merge, so per-commit hygiene matters for review readability, not the integration branch's history.
2. Rebase onto the latest integration branch
# Resolve $BASE (integration branch) — see git-ref "Integration Branch" (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 fetch origin
git rebase origin/"$BASE"If conflicts arise, resolve them in the working tree, then git add <files> and git rebase --continue. Abort with git rebase --abort if conflicts are too tangled — surface to the orchestrator via the signal file.
3. Push the feature branch
git push -u origin feat/<name>The -u (--set-upstream) flag is needed only on the first push; subsequent pushes can drop it.
---
Phase 10: Create PR / MR
Auto-detect the platform and target the integration branch:
# Resolve $BASE (integration branch) — see git-ref "Integration Branch" (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}
REMOTE_URL=$(git remote get-url origin)
case "$REMOTE_URL" in
*github.com*) gh pr create --title "<title>" --body "<body>" --base "$BASE" ;;
*gitlab*) glab mr create --title "<title>" --description "<body>" --target-branch "$BASE" ;;
*)
# Self-hosted GitHub Enterprise / Bitbucket / other host — pattern not matched.
# Do NOT silently no-op: open the PR/MR manually with the correct tool, always
# passing the base explicitly (--base "$BASE" / --target-branch "$BASE").
echo "Unrecognized remote host: $REMOTE_URL — create the PR/MR manually with base \"$BASE\"." >&2
exit 1
;;
esacCRITICAL — always specify `--base "$BASE"` (GitHub) or `--target-branch "$BASE"` (GitLab), resolving$BASEin the same block as above. Workspace sessions run from a worktree whose checked-out branch isfeat/<name>, not the integration branch. Without an explicit base,gh pr createmay infer the wrong base from the most recent merged branch — causing the PR to target a stale base and never land on the integration branch even after merge. In two-branch mode an inferred base could be productionmain, which AEP must never merge feature work into directly.
Include in the PR/MR body:
- Summary of changes (from proposal)
- Test coverage notes
- Link to manual test plan (if created)
---
Phase 11: PR Review & CI Feedback Loop
Monitor for CI and review feedback.
Triage review comments
Fix — correctness issues, CI failures, convention violations, security. Acknowledge but skip — style preferences, over-engineering, cosmetic suggestions. Discuss — architectural suggestions that expand scope, conflicting comments.
Fix loop
1. Triage all comments 2. Create fix plan at .dev-workflow/pr-fix-plan-<round>.md 3. Reply to skipped/discussed comments 4. Add follow-up commits for each fix:
# ... make the fix ...
git add -A
git commit -m "fix(<scope>): address review feedback on <topic>"Squash-merge at PR-merge time keeps the integration branch's history clean, so per-commit hygiene on the feature branch only matters for reviewer readability. 5. Re-run tests 6. Re-push:
git push origin feat/<name>7. Repeat until CI green and reviews resolved
---
Phase 11.5: Human Evaluation & Iteration
After PR review fixes are resolved, the human tester evaluates the feature — typically by running the app from the workspace. If they find minor issues (UX tweaks, missing edge cases, behavior that doesn't match intent), this phase handles the iteration loop.
If no issues found: Skip this phase and proceed to Phase 12.
Iteration round
1. Document findings — Write to .dev-workflow/human-eval-round-<N>.md:
- What was found (description, steps to reproduce)
- Severity (minor / moderate)
- Category (UX, logic, edge case, visual)
2. Add a follow-up commit per fix:
# ... make the fix ...
git add -A
git commit -m "fix(<scope>): <human-eval finding>"3. Align OpenSpec change — Update openspec/changes/<name>/ artifacts:
- Add completed tasks to
tasks.mdfor the work just done - Update
specs/if behavior changed - Update
design.mdonly if approach details shifted - Keep
proposal.mdscope as-is (direction unchanged)
4. Re-test — Re-run Phase 5 (code review) and Phase 6 (dogfood) on the changed areas.
5. Push — Update the PR:
git push origin feat/<name>6. Repeat — If the human tester finds more issues, start a new round.
Signal update: Create.dev-workflow/signals/ready-for-review.flagwhen ready for human evaluation. Updatestatus.jsonwith"phase": 11.5, "phase_name": "human-evaluation". This is a human gate — also follow the Human-Gate Protocol (needs-human.md +blocked_on: "human"+ your mode's transport) so the orchestrator surfaces it instead of counting you as stuck.
---
Phase 12: Pre-merge Checks & Merge
1. Up-to-date with the integration branch:
# Resolve $BASE — see git-ref "Integration Branch" (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 fetch origin && git rebase origin/"$BASE" && git push --force-with-lease origin feat/<name>2. CI checks green 3. No unresolved review comments 4. E2E tests passed (if applicable) 5. Present final status summary 6. Merge decision:
- Interactive mode (user present in session): Ask user for confirmation before merging
- Autopilot mode (launched via
/aep-launchinto.feature-workspaces/): Merge immediately when all pre-merge checks pass — do not wait for user confirmation. The autopilot orchestrator monitors via signals, not interactive prompts. - Detection: If your working directory is inside
.feature-workspaces/, you are in autopilot mode.
Merge:
REMOTE_URL=$(git remote get-url origin)- GitHub:
gh pr merge <number> --squash --delete-branch - GitLab:
glab mr merge <number> --squash --remove-source-branch
Why `--force-with-lease`: rebasing rewrites the feature branch's commit SHAs. --force-with-lease forces the push only if the remote hasn't advanced since you last fetched — protecting concurrent collaborators while still letting you push the rebased history.---
Guardrails
- Never skip the tracking initialization (Phase 0). Every workflow needs a progress file and contracts.
- Never run `/opsx:archive` from a workspace — it writes to
openspec/specs/and causes conflicts. Archive always runs on the integration branch via/aep-wrap. - Never write to `product-context.yaml` from a workspace — only the main session writes to the YAML. Report all status through
.dev-workflow/signals/status.json. This is the concurrency protocol. - Always confirm with the user before creating PRs, merging, or pushing to shared branches.
- The `.dev-workflow/` folder is ephemeral — gitignored, local to each workspace.
- Resume support: If returning to an in-progress workflow, run
.dev-workflow/init.shif it exists, then read the progress file. - Phase skipping: Users may ask to skip phases. Update progress file accordingly.
- One commit per task in Phase 4 — the PR review reads cleanly when the commit list mirrors
tasks.md. Don't bundle multiple tasks into one commit; don't split one task across multiple commits. - Don't rewrite history mid-stream — once you've moved past a committed task, fixes go in as new commits, not amends or rebases. Squash-merge at PR-merge handles the cleanup.
- Use `git push --force-with-lease`, never `--force` — the
leasevariant fails safely if someone else pushed to the same branch since your last fetch. - Signal updates are required — update
.dev-workflow/signals/status.jsonat the start and end of every phase. Check.dev-workflow/signals/feedback.mdfor main session feedback at phase boundaries. - Generator must not modify verification data — never modify
verification_stepsorpassesinfeature-verification.json. Onlycommit_shais generator-writable. The evaluator or human updatespasses/evaluated_by/round. - Evaluator loop max 5 rounds, climbing the recovery ladder — the generator escalates its strategy per round (same fix → re-ground → fresh generator → decompose) per
recovery-ladder.md; only once the ladder is exhausted (after round 5) does it escalate to human aseval_not_converging. Hard-failure/security FAILs skip the ladder and escalate on the first occurrence. - Raise human gates, don't guess — decisions only the human can make go through the Human-Gate Protocol (
needs-human.md+blocked_on: "human"+ your mode's transport). Silent stalls read as stuck; unrecorded guesses read as scope drift.
---
Next Step
After merge, signal the main session to run:
/aep-wrapSprint Contract Template
A sprint contract is generated during Phase 0 for each task in tasks.md. It bridges the gap between OpenSpec's high-level specs and concrete implementation by defining what will be built and how success will be verified before any code is written.
Anthropic's harness design research found that having the generator propose implementation details and success criteria — then having the evaluator review them before coding begins — prevents the common failure where agents build the wrong thing. This "sprint contract" negotiation continues until both sides agree.
Source: Harness Design for Long-Running Application Development
---
How Contracts Are Generated
During Phase 0:
1. Read tasks.md for the task list (this is your linear plan — one commit per task in Phase 4) 2. Read specs/*.md for detailed requirements 3. Read design.md for technical approach 4. For each task, extract the matching spec requirements and generate a contract
Contracts are written to .dev-workflow/contracts.md as a single file with one section per task.
---
Contract Format
# Sprint Contracts
Generated from OpenSpec change: <change-name>
Date: <YYYY-MM-DD>
---
## Task: <task description from tasks.md>
**Source spec:** <which spec file this maps to>
**Commit SHA:** <filled in after Phase 4 commits this task; 8-char short SHA>
### What will be built
- [Specific files to create or modify]
- [Components, routes, or endpoints to add]
- [Database changes if any]
### Success criteria
- [Extracted from matching spec — what "done" looks like]
- [Observable behaviors, not implementation details]
- [Include error and edge case handling from spec]
### Verification steps
1. [Concrete, executable step — e.g., "Navigate to /settings"]
2. [What to check — e.g., "Verify form shows current values"]
3. [Edge case — e.g., "Submit with empty required field, verify error shown"]
4. [Error path — e.g., "Disconnect network, verify offline message"]
### Dependencies
- [Other tasks this depends on, if any]
- [External services or APIs needed]
### Risks
- [Known unknowns or areas of uncertainty]
------
Example Contract
## Task: Add password reset flow
**Source spec:** specs/authentication.md
**Commit SHA:** a1b2c3d4
### What will be built
- `apps/web/src/pages/forgot-password.tsx` — Request reset form
- `apps/web/src/pages/reset-password.tsx` — New password form
- `apps/server/src/routes/auth/reset.ts` — Reset token API endpoints
- `packages/db/src/schema/reset-tokens.ts` — Token table schema
- Email template for reset link
### Success criteria
- User can request a password reset by entering their email
- System sends a reset email with a time-limited token
- User can set a new password using the token link
- Expired tokens show a clear error message
- Invalid tokens show a clear error message
- After reset, user is redirected to login
### Verification steps
1. Navigate to /forgot-password
2. Enter a registered email, submit — verify success message shown
3. Check server logs for reset email sent
4. Navigate to /reset-password?token=<valid-token>
5. Enter new password, submit — verify redirect to /login
6. Log in with new password — verify success
7. Try /reset-password?token=<expired-token> — verify "expired" error
8. Try /reset-password?token=<invalid-token> — verify "invalid" error
9. Submit /forgot-password with unregistered email — verify same success message (no email enumeration)
### Dependencies
- Authentication system from Task 1 must be complete
- Email service must be configured
### Risks
- Email delivery may be slow in dev environment
- Token expiration timing needs to be configurable---
Rules
1. Contracts are written before implementation — they capture intent, not after-the-fact documentation 2. Success criteria come from specs — don't invent new requirements 3. Verification steps must be concrete — "verify it works" is not a valid step 4. The generator writes contracts, the evaluator reviews them — if a separate evaluator is running, it checks contracts before Phase 4 begins 5. Contracts are not immutable — if implementation reveals the contract was wrong, update it and note why 6. Contracts feed into `feature-verification.json` — the verification steps are extracted into the JSON verification list for the evaluator
Development Progress
| Field | Value |
|---|---|
| Feature | <!-- feature name --> |
| Branch | <!-- feat/<name> --> |
| Base commit | <!-- short SHA from git rev-parse --short HEAD at branch creation --> |
| Started | <!-- YYYY-MM-DD --> |
| OpenSpec Change | <!-- change name --> |
| Mode | <!-- full / light --> |
| Evaluator | <!-- yes / no --> |
---
Part A — Scaffold
- [ ] Project scaffolded via Better-T-Stack
- [ ] OpenSpec initialized
- [ ] Build verified
Part B — Design (on main)
- [ ] Phase 1: OpenSpec Explore
- [ ] Phase 2: OpenSpec Propose
- [ ] Phase 3: Design Review
- [ ] Artifacts committed to main
Part C — Launch Workspace
- [ ] Worktree created (
git worktree add -b feat/<name>) - [ ] Workspace agent started via executor (mode: native-bg-subagent / claude-bg / codex-subagent / codex-exec / legacy tmux / workflow)
- [ ] Bootstrap prompt sent
- [ ] Evaluator agent launched (full mode only)
Part D — Implementation (in workspace)
- [ ] Phase 0: Tracking initialized
- [ ] Progress file created
- [ ] tasks.md read (linear plan, one commit per task)
- [ ] Dependencies installed
- [ ] Dev server running
- [ ] Port config written
- [ ] Sprint contracts generated (
.dev-workflow/contracts.md) - [ ] Feature verification list generated (
.dev-workflow/feature-verification.json) - [ ] Session recovery script generated (
.dev-workflow/init.sh) - [ ] Inter-agent signals initialized (
.dev-workflow/signals/) - [ ] Phase 4: OpenSpec Apply (one commit per task)
- [ ] Task 1: <!-- task description --> — commit: <!-- short SHA -->
- [ ] Task 2: <!-- task description --> — commit: <!-- short SHA -->
- [ ] Task 3: <!-- task description --> — commit: <!-- short SHA -->
- [ ] Phase 5: Code Review & Verification
- [ ] Completeness check (per-commit review via
git show) - [ ] Contracts verified (
.dev-workflow/contracts.md) - [ ] Quality review (evaluator or self-review)
- [ ] Evaluator round 1: <!-- PASS/FAIL + summary -->
- [ ] Evaluator round 2: <!-- if needed -->
- [ ]
feature-verification.jsonupdated - [ ] Issues fixed (follow-up commits)
- [ ] Phase 6: Browser Testing (Dogfood)
- [ ] Dogfood report created
- [ ] Issues fixed
- [ ] Phase 7: E2E Test Scripts
- [ ] Test scripts generated
- [ ] Tests passing
- [ ] Phase 8: Review Results
- [ ] All results reviewed
- [ ] No blocking issues
- [ ] Phase 9: Cleanup & Publish
- [ ] Commit history reviewed (
git log --oneline "$BASE"..HEAD) - [ ] Rebased onto latest
origin/$BASE(integration branch) - [ ] Pushed (
git push -u origin feat/<name>) - [ ] Phase 10: Create PR
- [ ] PR created (
gh pr create --base "$BASE") - [ ] PR URL: <!-- url -->
- [ ] Phase 11: PR Review Loop
- [ ] Round 1: <!-- status -->
- [ ] Phase 11.5: Human Evaluation & Iteration
- [ ] Iteration round 1: _[findings summary]_
- [ ] Findings documented
- [ ] Code fixed (follow-up commit)
- [ ] OpenSpec change aligned
- [ ] Re-tested
- [ ] Pushed
- [ ] Iteration round 2: _[findings summary]_
- [ ] Phase 12: Merge
- [ ] CI green
- [ ] Reviews resolved
- [ ] User confirmed
- [ ] Merged (
gh pr merge --squash --delete-branch)
Part E — Post-Merge (on the integration branch)
- [ ] Phase 13: Archive & Cleanup
- [ ] Fetched merged state (
git fetch && git pull --ff-only origin "$BASE") - [ ] Dev server stopped
- [ ]
/opsx:archiverun - [ ] Archive committed + pushed
- [ ] Worktree removed (
git worktree remove .feature-workspaces/<name> && git branch -d feat/<name>)
Worktree Onboarding
This document is the bootstrap guide for spawned agents running in a git worktree. Read this first when entering a workspace session.
Context
You are an agent spawned in an isolated git worktree to implement a feature autonomously. The design phases (1-3) were completed on the integration branch by the user, and /aep-launch created your worktree on a fresh feat/<name> branch. Your job is to execute Phases 0, 4-12.
Know your launch mode
How you were started determines how you reach the human and how the orchestrator reaches you (full table: aep-executor/references/backends.md):
| You are… | Mode | You raise human gates via… |
|---|---|---|
a Claude Code bg subagent (Agent tool, run_in_background, no team — bare-hex agentId) | native-bg-subagent | needs-human.md, then gate-and-park (commit WIP, end run cleanly) |
| a Claude Code session whose cwd is the worktree (background session) | claude-bg | needs-human.md, then park (commit WIP, end run cleanly) |
| a Codex subagent (aep-builder role, parent thread exists) | codex-subagent | ask the parent thread + needs-human.md; wait in place |
a headless codex exec run | codex-exec | needs-human.md, then park |
| a dynamic-workflow build agent | workflow | needs-human.md + return a structured gated result, then park |
| inside a tmux pane | legacy | needs-human.md; wait in place (answer arrives via nudge) |
Whatever the mode: your prompt names your worktree path — operate exclusively inside it, and report everything through .dev-workflow/signals/. The answer always comes back via the main agent (hub-and-spoke); parked workers are resumed into this worktree with the answer. The human-gate steps are in /aep-build SKILL.md ("The Human-Gate Protocol").
Bootstrap Sequence
1. Orient yourself
# Where am I? Which branch? What's the base?
pwd
git branch --show-current
git log --oneline -5
# What's the OpenSpec change?
ls openspec/changes/2. Read all change artifacts
# Read the full change context
cat openspec/changes/<change-name>/proposal.md
cat openspec/changes/<change-name>/aep-design.md
cat openspec/changes/<change-name>/tasks.md
ls openspec/changes/<change-name>/specs/ 2>/dev/null3. Initialize tracking and harness artifacts
mkdir -p .dev-workflow .dev-workflow/signals
# Copy progress template (named by base commit SHA for traceability)
cp skills/agentic-development-workflow/build/references/progress-template.md \
.dev-workflow/progress-$(git rev-parse --short HEAD).md
# Ensure .dev-workflow is gitignored
grep -q '.dev-workflow' .gitignore || echo '\n.dev-workflow/' >> .gitignoreEdit the progress file:
- Fill in feature name, base commit SHA, date, change name, mode (full/light)
- Mark Phases 1-3 as
[x](pre-completed on main)
4. Set up environment
Run the project's setup hook if it exists:
SETUP_HOOK=.claude/hooks/workspace-setup.sh
if [ -f "$SETUP_HOOK" ]; then
bash "$SETUP_HOOK"
else
echo "No workspace setup hook found at $SETUP_HOOK"
echo "Read the project README or ask the user for setup instructions."
fiThe setup hook handles project-specific concerns: package installation, dev server, port assignment, DB seeding, etc. It must write .dev-workflow/ports.env with WEB_PORT, SERVER_PORT, BASE_URL, SERVER_URL.
Verify setup produced ports.env:
[ -f .dev-workflow/ports.env ] && source .dev-workflow/ports.env5. Generate harness artifacts
After reading tasks.md (see SKILL.md Phase 0 step 6), generate these additional artifacts:
- Sprint contracts —
.dev-workflow/contracts.md: Per-task success criteria and verification steps extracted from OpenSpec specs. Seereferences/contract-template.mdfor the format. - Feature verification list —
.dev-workflow/feature-verification.json: JSON verification list for evaluator scoring.commit_shastarts asnulland is filled in after each task is committed in Phase 4. Generator must NOT modifyverification_stepsorpassesfields. - Session recovery script —
.dev-workflow/init.sh: Auto-generated script for resuming after context resets. Make executable withchmod +x. - Inter-agent signals —
.dev-workflow/signals/status.json: Initialize with current phase. Seereferences/signals-spec.mdfor the full specification.
6. Begin implementation
Now follow the workflow starting from Phase 4: OpenSpec Apply.
Read the full workflow at the /aep-build skill (skills/agentic-development-workflow/build/SKILL.md) for phase details.
---
Resuming a Session
If you are resuming an interrupted session (context reset, crash, manual restart):
1. Check for init.sh — if .dev-workflow/init.sh exists, run it:
bash .dev-workflow/init.shThis restarts the dev server, shows the branch state, and displays progress. This is preferred over full context resets because it preserves structured state from previous sessions.
2. Read the progress file to find your current phase:
cat .dev-workflow/progress-*.md3. Check for pending feedback from the main session:
cat .dev-workflow/signals/feedback.md 2>/dev/null4. Continue from where you left off — pick up at the first unchecked phase. Inspect prior commits via git log --oneline "$(git config --get aep.integration-branch 2>/dev/null || (git show-ref --verify --quiet refs/remotes/origin/develop && echo develop || echo main))"..HEAD to see what's already implemented.
Do NOT re-run the full bootstrap if .dev-workflow/ already exists. Use init.sh for recovery.---
Key Rules
- Update the progress file after completing each phase
- Update signals — write to
.dev-workflow/signals/status.jsonat phase boundaries, checkfeedback.mdfor main session input - Never run `/opsx:archive` — that happens on main after merge
- Don't stage `openspec/specs/` files in your commits
- Ask for confirmation before creating PRs or merging
- The `.dev-workflow/` folder is ephemeral — never commit it
- Generator must not modify verification data — never change
verification_stepsorpassesinfeature-verification.json. Onlycommit_shais generator-writable. - One commit per task in Phase 4 — keeps the PR review readable. Squash-merge at PR-merge cleans up main history.
- Don't rewrite already-pushed commits — fixes go as follow-up commits. If you need to amend, do it before the next task's commit.