| name | create-feature |
| description | Orchestrates a full feature lifecycle: receive goals, synthesize detailed specs, propose via OpenSpec, commit & push, apply tasks, audit results, update PR, and post audit results as a comment. |
| license | BSD 3-Clause |
| compatibility | Requires Node.js 24+, npm, git with remote access, gh CLI, openspec CLI, and a project root with openspec/ directory. When invoked as a sub-agent, requires a 30–60 minute timeout — the full pipeline (spec → implement → test → archive → PR) can take that long. |
| metadata | {"agent":"coding"} |
Create Feature
Orchestrate a complete feature lifecycle from raw goals to shipped code. This is the full pipeline — synthesis, specification, implementation, verification, and delivery.
Prerequisites
Before starting, ensure:
- You are in the project root directory (contains
package.json, openspec/)
gh CLI is authenticated and configured
openspec CLI is available
- The current branch is
main (or will be checked out at step 0)
Input
The user provides a list of goals/features in any format (natural language, JSON, markdown list, etc.). Parse and normalize them into a clean array of goal strings.
Example input:
Add a new tool that can summarize web pages, and improve the TUI memory panel to show retention stats.
Normalized goals:
- Add a new tool that can summarize web pages
- Improve the TUI memory panel to show retention stats
Step 0: Ensure Clean State
git checkout main
git pull origin main
Verify the working tree is clean:
git status --porcelain
If there are uncommitted changes, report them and stop. Do not proceed with a dirty tree.
Step 0.5: Capture Session ID
Capture a unique session identifier. All memory files are prefixed with this ID so that multiple instances (e.g., subagents) can run in parallel without file collisions.
SESSION_ID=$(head -c 8 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n' || echo $RANDOM$RANDOM$RANDOM)
echo "SESSION_ID=$SESSION_ID"
All subsequent memory file paths use the pattern memory/${SESSION_ID}-<name>.
Step 1: Synthesize Detailed Goals
Take the raw goals from the input and expand each into a more detailed, actionable specification. For each goal, produce:
- Goal: The original goal string
- Scope: What is included and explicitly excluded
- Key Requirements: 3-5 concrete requirements
- Acceptance Criteria: How success is measured
- Dependencies: Any existing code, configs, or specs that need to change
- Risks / Edge Cases: Potential pitfalls to consider
Write the detailed goals to memory/${SESSION_ID}-feature-goals.md as a markdown document. This file serves as the source of truth for all subsequent audits.
Step 2: Synthesize Proposal Prompt
Using the detailed goals from Step 1, synthesize a multi-paragraph proposal prompt suitable for feeding into openspec-propose. The prompt should:
- Start with a parseable change name on the first line:
CHANGE_NAME: <kebab-case-name> (e.g., CHANGE_NAME: web-page-summarizer-tui-memory-stats)
- Include a concise summary of what is being built and why
- Describe the technical approach in 2-4 paragraphs
- Reference specific files, modules, and patterns in the codebase
- Note any architectural decisions or trade-offs
- Be specific enough that
openspec new change + artifact generation will produce useful specs
Write the proposal prompt to memory/${SESSION_ID}-feature-prompt.md.
Step 3: Extract Change Name
Parse the change name from the proposal prompt in Step 2. This is the kebab-case identifier that will be used for the OpenSpec change directory.
CHANGE_NAME=$(grep -oP '(?<=CHANGE_NAME: )\S+' memory/${SESSION_ID}-feature-prompt.md | head -1)
if [ -z "$CHANGE_NAME" ]; then
CHANGE_NAME=$(basename "$(pwd)" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
fi
echo "CHANGE_NAME=$CHANGE_NAME"
Step 3.5: Create Feature Branch
Create a feature branch following the project rules §5.2 branching rules. Strip any existing feat/ or fix/ prefix from $CHANGE_NAME to avoid double-prefixing:
BRANCH_NAME=$(echo "$CHANGE_NAME" | sed 's/^\(feat\|fix\)\///')
git checkout -b "feat/$BRANCH_NAME"
Verify the branch was created:
git branch --show-current
Step 4: Create OpenSpec Change
Run the OpenSpec propose workflow for the synthesized change:
openspec new change "$CHANGE_NAME"
Then generate all artifacts using this procedure (optimized for the automated pipeline):
-
Get the artifact build order:
openspec status --change "$CHANGE_NAME" --json
-
For each artifact that is ready (dependencies satisfied):
- Get instructions:
openspec instructions <artifact-id> --change "$CHANGE_NAME" --json
- Read any completed dependency files for context
- Create the artifact file using the template and following the instructions
- Re-run
openspec status --change "$CHANGE_NAME" --json after each artifact
-
Continue until all applyRequires artifacts are complete.
After completion, verify all expected files exist:
ls -la openspec/changes/$CHANGE_NAME/
Expected files: .openspec.yaml, proposal.md, design.md, tasks.md, and any spec deltas in specs/.
If any expected file is missing, stop and report the error.
Step 5: Audit Specs Against Goals (Up to 3 Iterations)
Read the detailed goals from memory/${SESSION_ID}-feature-goals.md and the generated spec documents (proposal.md, design.md, tasks.md, and any spec deltas).
Perform a thorough audit:
- Coverage audit: Does every detailed goal have corresponding requirements in the specs?
- Fidelity audit: Do the specs faithfully represent the original intent of each goal?
- Completeness audit: Are there missing requirements, edge cases, or acceptance criteria not captured?
- Consistency audit: Do the tasks in tasks.md map to the requirements in the specs?
Write audit findings to memory/${SESSION_ID}-audit-results.md.
If errors are found:
- Fix the spec documents to address each finding
- Update tasks.md if task-to-spec mapping is broken
- Re-audit (increment iteration count)
- Repeat until no errors remain or 3 iterations are exhausted
If no errors are found:
Step 6: Commit & Push (via commit-push)
Do not perform git operations inline. Invoke the commit-push skill to handle staging, committing, pushing, and PR creation.
commit-push
The commit-push skill will:
- Stage all changes
- Commit using conventional commit format from the scanned project rules §5.1
- Push to the remote
- Create a PR using the template from the scanned project rules §5.4
After /commit-push completes, extract the PR number from its output and save it:
echo "$PR_NUMBER" > memory/${SESSION_ID}-pr-number.txt
If /commit-push fails, report the error and stop. Do not attempt to recover with manual git commands.
Step 7: Apply Tasks
Execute tasks using this procedure (simplified for the automated pipeline context):
- Read
openspec/changes/$CHANGE_NAME/tasks.md for all unchecked tasks.
- Create a todo queue mapping each unchecked task to a todo item.
- Execute tasks sequentially in creation order.
- When a task completes, mark it
[x] in tasks.md.
- If a task fails, report the error and stop. Do not continue with incomplete work.
- Continue until all tasks are complete or the queue is exhausted.
After completion, verify:
- All tasks in
tasks.md are marked [x]
- Tests pass:
npm run test
- Lint passes:
npm run lint
- Coverage is maintained:
npm run coverage
If any verification fails, fix the issues and re-verify.
Step 8: Verify Application Starts (npm start)
After tasks are applied, verify the application actually starts without crashing:
npm start
Run it in the background and watch for startup errors:
timeout 10 npm start 2>&1 || true
Or run it as a background process and check for immediate crashes:
npm start &
APP_PID=$!
sleep 5
if kill -0 $APP_PID 2>/dev/null; then
echo "Application started successfully (PID $APP_PID)"
kill $APP_PID 2>/dev/null || true
else
echo "WARNING: Application crashed on startup"
fi
wait $APP_PID 2>/dev/null || true
If the application fails to start, fix the issue before proceeding. Do not skip this step — a crashing application means the implementation is flawed.
Step 9: Audit Results Against Specs & Goals (Up to 3 Iterations)
Read the original goals from memory/${SESSION_ID}-feature-goals.md and the spec documents. Audit the implemented results:
- Goal fulfillment: Does the implementation satisfy every detailed goal?
- Spec compliance: Does the code match the requirements in the spec documents?
- Task completion: Were all tasks in tasks.md actually implemented correctly?
- Quality check: Are there any obvious issues, missing edge cases, or inconsistencies?
Write audit findings to memory/${SESSION_ID}-audit-results.md (overwrite previous results).
If errors are found:
- Fix the code to address each finding
- Re-verify tests and lint pass
- Re-audit (increment iteration count)
- Repeat until no errors remain or 3 iterations are exhausted
If no errors are found:
Step 10: Archive the OpenSpec Change
Archive the completed OpenSpec change with automatic sync:
-
Run the archive:
openspec archive "$CHANGE_NAME" --yes
-
When presented with a sync prompt, automatically choose sync (the recommended option). Do not require user input — just select sync:
- If the prompt shows "Sync now (recommended)" / "Archive without syncing" → choose "Sync now (recommended)"
- If the prompt shows "Archive now" / "Sync anyway" / "Cancel" → choose "Archive now"
- If no delta specs exist → proceed without sync prompt
-
Verify the archive was created:
ls openspec/changes/archive/
The change directory should now be under openspec/changes/archive/YYYY-MM-DD-<name>/.
Step 11: Commit & Push Implementation Fixes
If any fixes were made in Step 8, commit and push them by invoking commit-push:
commit-push
If no fixes were needed, skip this step.
Step 12: Update PR Title & Description
Use gh api to update the PR title and body with the final, accurate description of what was implemented.
-
Gather the actual changes made:
git diff main...HEAD --stat
git diff main...HEAD --name-only
-
Synthesize a final PR description that:
- Reflects what was actually implemented (not just what was planned)
- References specific files and modules changed
- Notes any deviations from the original plan
- Includes testing coverage summary
- Follows the PR template format from the scanned project rules
-
Read the PR number and update the PR:
PR_NUMBER=$(cat memory/${SESSION_ID}-pr-number.txt)
gh pr edit "$PR_NUMBER" --title "feat: $CHANGE_NAME — <final title>" --body "<final body>"
Step 13: Post Audit Results as PR Comment
Post the final audit results from Step 9 as a comment on the PR:
PR_NUMBER=$(cat memory/${SESSION_ID}-pr-number.txt)
gh pr comment "$PR_NUMBER" --body "$(cat memory/${SESSION_ID}-audit-results.md)"
Step 14: Final Report
Print a summary:
Feature lifecycle complete.
Change: $CHANGE_NAME
PR: <URL>
Goals addressed: <count>/<total>
Iterations: <spec-audit-x>, <impl-audit-y>
Tests: passing
Lint: passing
Coverage: maintained
Step 15: Cleanup
Remove the intermediate memory files — they served their purpose and won't be needed again:
rm -f memory/${SESSION_ID}-feature-goals.md memory/${SESSION_ID}-feature-prompt.md memory/${SESSION_ID}-audit-results.md memory/${SESSION_ID}-pr-number.txt
Verify cleanup:
ls memory/${SESSION_ID}-feature-*.md memory/${SESSION_ID}-audit-results.md memory/${SESSION_ID}-pr-number.txt 2>&1
If any files remain, report them and remove manually.
Error Handling
- If any step fails, report the error clearly and stop. Do not continue with incomplete work.
- If 3 audit iterations are exhausted and errors remain, report the remaining issues and stop.
- If
gh API calls fail, report the error and provide the manual commands needed.
- Always leave the repository in a clean state (working tree clean, on the feature branch).