From agentic-development-workflow
Archives OpenSpec change, commits archive, and cleans workspace after a PR merge. Run from integration branch when the user says 'wrap up', 'archive', or 'cleanup after merge'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agentic-development-workflow:wrapThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Post-merge archive and workspace cleanup. Run this on the **integration branch** (`$BASE` — `main` in single-branch mode, `develop` in two-branch mode; see [git-ref](../git-ref/SKILL.md) → "Integration Branch") after the PR merges to archive the OpenSpec change and clean up the workspace.
Post-merge archive and workspace cleanup. Run this on the integration branch ($BASE — main in single-branch mode, develop in two-branch mode; see git-ref → "Integration Branch") after the PR merges to archive the OpenSpec change and clean up the workspace.
Where this fits:
/aep-onboard → /aep-scaffold → [ /aep-design → /aep-launch → /aep-build → /aep-wrap ]
▲ you are here
Session: Main session, post-merge Input: Merged PR notification Output: Archived OpenSpec change, cleaned up workspace
Run on the integration branch (
$BASE) after the PR merges. Do not run from the workspace.
# 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 checkout "$BASE"
git pull --ff-only origin "$BASE"
git status
Update the local integration branch to include the merged workspace PR.
--ff-onlyis intentional — if it fails because$BASEhas unpushed local commits, push or rebase those first.After this checkout you are on the integration branch; later steps recover its name with
BASE=$(git branch --show-current)(HEAD persists across shells, so this is safe even in a fresh command).Check for lost OpenSpec changes: If the dispatch commit included OpenSpec changes that are now missing (common if the dispatch commit wasn't pushed before launching), recover them from the original dispatch commit:
# Find the original dispatch commit git log --oneline -n 20 # Restore OpenSpec files from the dispatch commit git restore --source=<dispatch-commit-sha> -- openspec/Verify the workspace is clean before archiving. If
git statusshows unexpected modified files (code inapps/,packages/, etc.), investigate before proceeding. Onlyopenspec/andproduct-context.yamlfiles should change during the wrap step.
source .feature-workspaces/<name>/.dev-workflow/ports.env 2>/dev/null
lsof -ti :$SERVER_PORT | xargs kill 2>/dev/null
lsof -ti :$WEB_PORT | xargs kill 2>/dev/null
/opsx:archive <change-name>
BASE=$(git branch --show-current) # integration branch, checked out in step 1
git add openspec/
git commit -m "chore: archive <change-name>"
git pull --ff-only origin "$BASE"
git push origin "$BASE"
Standalone mode: If
product-context.yamldoesn't exist, skip this step and proceed to step 6.
If product-context.yaml exists and this feature was a dispatched story, read the workspace signals and cross-check against the actual PR state:
# Read completion data from workspace signals
cat .feature-workspaces/<name>/.dev-workflow/signals/status.json
# Cross-check: verify actual PR state (signals can be stale)
gh pr view <pr-number> --json state,mergedAt
Signal validation: Workspace agents don't always update their signal files after merge (they may show
in_revieweven though the PR is already merged). Always cross-check the signal'sstory_statusagainst the actual PR state viagh pr view. If the PR is merged but the signal saysin_review, treat the story ascompleted.
From the signal file (corrected by PR state if needed), extract story_status, pr_url, cost_usd, completed_at, and failure_log (if present). Update the story in product-context.yaml:
# Update the matching story:
status: completed # from signal story_status
completed_at: <timestamp> # from signal completed_at
pr_url: <url> # from signal pr_url
cost_usd: <cost> # from signal cost_usd
If story_status is failed, update with failure data instead:
status: failed
failure_logs:
- <structured failure_log from signal>
After updating the story, check if any pending stories should transition to ready (all dependencies now completed). Validate and commit all transitions atomically:
# Validate YAML before committing (see product-context references/yaml-guardrails.md)
npx js-yaml product-context.yaml > /dev/null && echo "YAML OK"
BASE=$(git branch --show-current) # integration branch, checked out in step 1
git add product-context.yaml
git commit -m "chore: update story <id> status to completed"
git pull --ff-only origin "$BASE"
git push origin "$BASE"
Concurrency protocol: This is the only place where story completion status enters
product-context.yaml. Workspace agents write to signals;/aep-wrap(running on the integration branch) reads signals and writes to YAML.
Before forgetting the workspace, check for lessons captured during the build:
LESSONS=".feature-workspaces/<name>/.dev-workflow/lessons.md"
if [ -f "$LESSONS" ] && [ "$(wc -l < "$LESSONS")" -gt 12 ]; then
# File has content beyond the template header
mkdir -p lessons-learned
cp "$LESSONS" "lessons-learned/<change-name>.md"
BASE=$(git branch --show-current) # integration branch, checked out in step 1
git add lessons-learned/<change-name>.md
git commit -m "docs: archive lessons from <change-name>"
git pull --ff-only origin "$BASE"
git push origin "$BASE"
fi
Why before worktree removal: Once
git worktree removeruns, the worktree directory and its.dev-workflow/lessons.mdare gone. This is the only chance to extract them.
If the lessons file contains only the template header (no Solutions, Errors, Missing, or Summary entries), skip — don't archive empty ceremony.
executor.teardown())Stop the workspace's worker before removing the worktree — otherwise an
OS-bound worker keeps running against a deleted directory, and these orphans
accumulate across an autopilot run. The stop step is per launch mode (recorded
as backend/agent_id in autopilot state, or evident from how you launched):
# Mode-specific worker stop (each is a no-op for the other modes):
# native-bg-subagent → TaskStop(<bare-hex bg-subagent id>) (session-bound, no team)
# claude-bg → claude stop <agent_id>; claude rm <agent_id>
# codex-subagent → close_agent(<agent_id>) if still running
# codex-exec → nothing to kill (the exec process exited with the build)
# legacy → tmux kill-session -t <name> 2>/dev/null || true
git worktree remove .feature-workspaces/<name> \
|| git worktree remove --force .feature-workspaces/<name> # --force only if leftover files block removal
git worktree prune
git branch -d feat/<name> # PR was merged → branch is reachable from the integration branch, safe to delete
If git branch -d warns the branch isn't fully merged (e.g., 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.
/opsx:archive from a workspace — it writes to openspec/specs/ and causes conflicts when parallel workspaces are active. Archive always runs on the integration branch ($BASE).git fetch && git pull --ff-only, run git status to verify no unexpected files are modified.openspec/changes/<name>/ is missing, the dispatch commit may have been lost. Recover from the original dispatch commit using git restore --source=<sha> before running archive.in_review after PR is merged). Always verify via gh pr view before updating product-context.yaml.git worktree remove runs, the worktree directory, signal files, and lessons.md are gone. Extract all needed data (status, lessons) first.Standalone mode: If
product-context.yamldoesn't exist, skip the layer gate check. You can still run/aep-reflectif you want to classify observations.
After archiving, check the product context:
If product-context.yaml exists and this feature was a dispatched story:
# Check: was this the last story in the current layer?
# Read product-context.yaml and check if all stories in the active layer are completed
If all stories in the current layer are completed, run the two-phase layer gate — a gate is green only when the layer is covered, not when one journey passes.
Read skills/e2e-test/policy.md first (if the project has the e2e-test skill): it declares the
applicable tiers (run only these — a none-target / CLI project has no Tier-2), the dogfood
target (none / local / deployed:<url>), and the timing. With journey_timing: post-deploy,
run the journey against the deployed:<url> target here (after merge/deploy) — that is what flips
scripted_passed → passed.
layer_gates[layer].status: scripted_passed and record the test file under evidence.scripted.dogfood_target == none (CLI/library
— Tier-2 N/A; prove criteria via Tier-1/Tier-3). Otherwise run the matching BDD journey/journeys in
skills/e2e-test/journeys/ (layer: N) via their tool-selection.md, plus any applicable API
drivers, and replay prior-layer journeys — seeding the policy's target first (a deployed:<url>
target needs SERVER_URL=<url> bash skills/e2e-test/scripts/seed.sh, not local). Record evidence —
screenshots, API JSON, PASS/FAIL per Then, and the two coverage matrices — in docs/layer-gates/<layer>.md.coverage.criteria_covered == criteria_total). Genuine gaps were already auto-closed during
/aep-build Phase 6; a deliberate deferral must carry a WAIVER: <reason> line. Never flip to
passed while criteria are silently uncovered.passed only when all applicable tiers are green AND coverage is complete-or-waived AND
the regression replay passed; set completed_at. If only Tier-1 passed, leave it scripted_passed.criteria_covered / criteria_total,
per-tier status, any waivers) and confirm with the user that the next layer's design should begin.
The gate flip is automatic-on-evidence; the advance is a human decision — the next /aep-dispatch
proceeds only after that confirmation.Consider running /aep-reflect to classify observations from this feature and update the product context:
/aep-reflect
This closes the feedback loop — bugs, refinements, and discoveries get routed back to the right phase.
Pick the next story from the dispatch queue:
/aep-dispatch
Or classify feedback from the feature you just shipped:
/aep-reflect
npx claudepluginhub memorysaver/agentic-engineering-patterns --plugin agentic-development-workflowAutonomously implements features in an isolated git worktree: initializes tracking, implements tasks linearly with one commit per task, reviews, tests, creates a PR, handles feedback, and merges.
Guides completion of development work—verify tests, run code review, audit test alignment, then present options for merge, PR, or cleanup.
Merges a PR, removes a Git worktree, and deletes the associated state file. Final phase of a multi-step local branch/PR workflow.