dx-step
Execute the next pending step in implement.md — implement, test, review, commit, update status. Use to go one step at a time ('next step').
- License 许可
- MIT
- 最近更新
- 2026-11-11
- Stars
- ★ 7
- Forks
- 3
01 前言 Front Matter
- name
- dx-step
- model
- sonnet
- context
- fork
- description
- Execute the next pending step in implement.md — implement, test, review, commit, update status. Use to go one step at a time ('next step').
- allowed-tools
- [ "read", "edit", "search", "write", "agent", "AEM/*" ]
- argument-hint
- [Work Item ID or slug (optional — uses most recent if omitted)]
03 SKILL.md 正文
Isolation check. This skill is meant to run in its own context (context: fork). If you can see the user's messages from before this skill was invoked, you are running inline (Copilot CLI ignores context: fork): do not run the steps below yourself. Start one subagent with your task/subagent tool, give it only this instruction — "Invoke the dx-core:dx-step skill with these arguments: <the arguments you were given, or none>. Run it fully and reply with its final report only." — then show the user that report and stop. If you cannot see earlier user messages, or your only earlier message is that instruction to invoke dx-core:dx-step (you are a fork or that subagent), continue below.
You execute the next pending step from implement.md — implement the changes, verify compilation, run tests, review against plan and conventions, commit, and mark the step done.
You run forked (context: fork): coordinators (dx-step-all, dx-bug-fix) call you once per step and read only your final ## Return block. Before printing anything user-facing, check whether a step loop is driving you (see plugins/dx-core/shared/orchestration-check.md § Step-loop marker):
IN_STEP_LOOP=0
LOOP_FLAG=".ai/run-context/step-loop.flag"
if [ -f "$LOOP_FLAG" ]; then
AGE=$(( $(date +%s) - $(date -r "$LOOP_FLAG" +%s) ))
[ "$AGE" -lt 7200 ] && IN_STEP_LOOP=1
fi
You are the worker for one step. Never invoke Skill(dx-step) or /dx-step-all yourself. The loop belongs to the coordinator.
$IN_STEP_LOOP == 1 only suppresses the "run X next" hints addressed to a human — it never changes what the step does.
Progress Tracking
Follow .ai/rules/task-progress.md (plugin default: rules/task-progress.md). The progress file is the source of truth — write it at every step transition:
DX_PROGRESS_FILE="dev-all-progress.md" DX_PROGRESS_TITLE="Pipeline Progress" \
bash "${CLAUDE_PLUGIN_ROOT}/shared/update-progress.sh" "$SPEC_DIR" "<n>: <title>" "<status>"
The row key is <n>: <title> — the step number and title exactly as they appear
in implement.md. dx-step-all invokes this skill once per step and writes the
same file with the same key and the same DX_PROGRESS_TITLE, so a step must
produce one row however it was started, and dx-agent-all counts it (its
counters anchor on ^\| [0-9]+:). Never key a row on a free-form label.
Status values: pending · in_progress · done · failed · skipped · blocked. One row per step, updated in place.
If TaskCreate is in this session's tool list, also mirror the same steps into tasks so the user gets a live checklist — TaskList first to cancel stale tasks from an interrupted run. If it is absent (the default on Opus 4.8 / Sonnet 5 / Fable 5 / Mythos 5 and newer), skip that silently and rely on the file. Never block a step transition on a task tool being present.
Flow
digraph step {
"Locate spec directory" [shape=box];
"Hub mode check" [shape=diamond];
"Find next step" [shape=diamond];
"All done" [shape=doublecircle];
"Step status?" [shape=diamond];
"Mark in-progress" [shape=box];
"AEM MCP Pre-Check" [shape=box];
"Execute the step" [shape=box];
"Verify compilation" [shape=box];
"Verification passed?" [shape=diamond];
"Classify error" [shape=diamond];
"TRANSIENT: Retry" [shape=box];
"Retry passed?" [shape=diamond];
"VALIDATION: Auto-fix" [shape=box];
"Auto-fix passed?" [shape=diamond];
"Run tests" [shape=box];
"Tests passed?" [shape=diamond];
"Review against plan" [shape=box];
"Review passed?" [shape=diamond];
"Stage and commit" [shape=box];
"Commit succeeded?" [shape=diamond];
"Mark done + present summary" [shape=doublecircle];
"Mark blocked + present summary" [shape=doublecircle];
"Locate spec directory" -> "Hub mode check";
"Hub mode check" -> "Find next step" [label="not hub mode"];
"Hub mode check" -> "All done" [label="hub dispatched"];
"Find next step" -> "All done" [label="none pending"];
"Find next step" -> "Step status?" [label="found"];
"Step status?" -> "Mark in-progress" [label="pending"];
"Step status?" -> "AEM MCP Pre-Check" [label="in-progress (resume)"];
"Step status?" -> "Find next step" [label="blocked (skip)"];
"Mark in-progress" -> "AEM MCP Pre-Check";
"AEM MCP Pre-Check" -> "Execute the step";
"Execute the step" -> "Verify compilation";
"Verify compilation" -> "Verification passed?";
"Verification passed?" -> "Run tests" [label="yes"];
"Verification passed?" -> "Classify error" [label="no"];
"Classify error" -> "TRANSIENT: Retry" [label="TRANSIENT"];
"Classify error" -> "VALIDATION: Auto-fix" [label="VALIDATION"];
"Classify error" -> "Mark blocked + present summary" [label="PERMANENT"];
"TRANSIENT: Retry" -> "Retry passed?";
"Retry passed?" -> "Run tests" [label="yes"];
"Retry passed?" -> "Mark blocked + present summary" [label="no"];
"VALIDATION: Auto-fix" -> "Auto-fix passed?";
"Auto-fix passed?" -> "Run tests" [label="yes"];
"Auto-fix passed?" -> "Mark blocked + present summary" [label="no"];
"Run tests" -> "Tests passed?";
"Tests passed?" -> "Review against plan" [label="yes"];
"Tests passed?" -> "Mark blocked + present summary" [label="no"];
"Review against plan" -> "Review passed?";
"Review passed?" -> "Stage and commit" [label="yes"];
"Review passed?" -> "Mark blocked + present summary" [label="no"];
"Stage and commit" -> "Commit succeeded?";
"Commit succeeded?" -> "Mark done + present summary" [label="yes"];
"Commit succeeded?" -> "Mark blocked + present summary" [label="no"];
}
Node Details
Locate spec directory
SPEC_DIR=$(bash .ai/lib/dx-common.sh find-spec-dir $ARGUMENTS)
Read implement.md from $SPEC_DIR.
Hub mode check
Read ../../shared/hub-dispatch.md for hub detection logic.
If hub mode is active (hub.enabled: true AND cwd is .hub/):
- Determine which repo owns this step:
- Read
implement.mdstep instructions for file paths - Match file paths to repo capabilities from config
- Or: if step specifies a repo tag (from cross-repo plan), use that
- Read
- Dispatch to the correct repo:
cd <repo.path> && claude -p "/dx-step <ticket-id>" --output-format json --allowedTools "Bash,Read,Edit,Write,Glob,Grep" --permission-mode bypassPermissions - Collect result, write state
- Print:
✓ <repo> — step <N> <status> - Go to → "All done" (step executed in target repo)
If hub mode is not active: continue to "Find next step" (normal flow).
Find next step
Parse implement.md and find the first step with **Status:** pending.
If a step has **Status:** in-progress, it was interrupted — route to "Step status?" with in-progress.
If a step has **Status:** blocked, skip it and find the next pending step. Print: "Skipping Step N (blocked). Executing Step M instead."
All done
- Check if implement.md has an
**Other repos required:**line. If so, print:> Cross-repo: This plan covers <current repo> only. Switch to <other repo(s)> and run `/dx-req <id>` there. - If
$IN_STEP_LOOP == 0, print: "All steps are done. Run/dx-prto create a pull request." - End with the
## Returnblock (verdict: pass,next_action: none — no pending steps).
Step status?
Route based on the step's current status:
- pending → go to "Mark in-progress"
- in-progress → go to "AEM MCP Pre-Check" (resume interrupted step — pre-check is idempotent)
- blocked → go back to "Find next step" (skip and find next pending)
Mark in-progress
Update the step's status in implement.md:
**Status:** in-progress
Note: When updating status in implement.md, preserve the provenance frontmatter block at the top of the file unchanged.
AEM MCP Pre-Check
Trigger: Only runs when the current step modifies files under aem.component-path or frontend component paths from config. Skip for pure Java, config, test-only, or non-component steps.
Prerequisite: aem.author-url-qa configured in .ai/config.yaml. If not configured, skip pre-check silently.
Three quick validation queries against AEM QA:
-
Component exists —
mcp__plugin_dx-aem_AEM__getNodeContenton the component definition path. If not found: warn "Component<name>not found on QA. May be new or not yet deployed. Skipping AEM pre-check." and skip remaining queries. -
Field exists —
mcp__plugin_dx-aem_AEM__getNodeContenton<component-path>/<name>/_cq_dialog(depth 6). Check that every dialog field referenced in the plan step actually exists in the dialog. If a referenced field is missing: warn "Plan references field<field>but it's not in the QA dialog. Possible: not yet deployed or field name is wrong." -
Field semantic check —
mcp__plugin_dx-aem_AEM__getNodeContenton a component instance from a known page (use pages fromresearch.mdAEM Component Intelligence, or query for one). Compare the plan's assumption about the field's purpose against the actualfieldLabeland authored value. If mismatch: warn "Plan says<field>is<plan assumption>, but QA shows label<actual label>with value<actual value>. Review the step."
All results are warnings — never block execution. The agent uses warnings to adjust its implementation approach if needed. Pre-check informs, does not gate.
What this does NOT do: No page scanning (init territory), no variant discovery (planning territory), no content comparison (aem-verify territory), no full dialog walk (aem-snapshot territory). This is a focused 3-query sanity check.
Execute the step
Incremental Implementation Principles
Before writing code, apply these guardrails:
- Vertical slices — implement the smallest complete piece of functionality. Each change should leave the system in a working state.
- Safe defaults — new code opts into behavior conservatively. New features default to OFF.
- Rollback-friendly — prefer additive changes (new files, new methods) over modifications. Additive changes are independently revertable.
- Scope discipline — touch only files listed in the step's Files: section. Note adjacent improvements in a comment, don't fix them.
- No premature abstraction — three similar lines of code beat a premature helper. Only abstract when the third use appears.
Read the step's full instructions:
- Files — which files to modify or create
- What — specific instructions for changes
- Why — requirement being addressed (for context)
Implement the changes:
- Read each file listed in Files before modifying it
- Follow the What instructions precisely
- Before creating any new utility, helper, or abstraction: search the codebase (
commons/,utils/,shared/,lib/,scripts/libs/,mixins/) for existing implementations. If one exists, use it instead of creating new code. Ifresearch.mdexists in the spec directory, check its "Existing Implementation Check" section for reusable code. - Use Edit tool for modifications, Write tool for new files
- Follow project conventions — read
.claude/rules/for rules matching the file types being modified (e.g.,fe-javascript.mdfor JS,fe-styles.mdfor SCSS). If.github/instructions/exists, also read the relevant instruction file for framework-specific patterns. For AEM frontend work involving modals, overlays, or focus traps, check ifshared/aem-dom-rules.mdexists (dx-aem plugin) and follow its DOM constraints.
Test-first approach:
If the step has a Test: line and superpowers:test-driven-development is available, invoke it to guide the RED-GREEN-REFACTOR cycle.
Fallback (if superpowers not installed): Follow the Red-Green-Refactor cycle from ../../shared/testing-patterns.md:
- RED: Write/locate the test first. Run it — confirm it fails (proves the test validates something).
- GREEN: Write the minimal implementation to pass the test. No extras (YAGNI).
- REFACTOR: Clean up only after green — duplication, naming, structure — while staying green.
If a test passes immediately before any code change, the test isn't validating new behavior — fix it.
Verify compilation
Run the step's Test command if specified. Otherwise, read the build command from .ai/config.yaml build.command and run a compile check (not full build):
If the project uses Maven: mvn compile -pl <module> -q
If the project uses npm: npm run build
Otherwise: use whatever compile/typecheck command is configured.
Verification passed?
- yes — compilation/test exits 0 → go to "Run tests"
- no — error detected → go to "Classify error"
Classify error
Classify the error against the taxonomy in ../../shared/error-handling.md:
- TRANSIENT → go to "TRANSIENT: Retry"
- VALIDATION → go to "VALIDATION: Auto-fix"
- PERMANENT → go to "Mark blocked + present summary"
TRANSIENT: Retry
Retry the command (up to 2 times). If still failing, go to "Mark blocked + present summary".
Retry passed?
- yes — retry succeeded → go to "Run tests"
- no — still failing after retries → go to "Mark blocked + present summary"
VALIDATION: Auto-fix
Attempt ONE auto-fix (syntax fix, missing import, lint fix). Re-run verification. Do NOT attempt more than one auto-fix.
Auto-fix passed?
- yes — fix + verify passes → go to "Run tests"
- no — fix fails or verify still fails → go to "Mark blocked + present summary"
Run tests
Determine the test command:
- Check the current step's Test: line
- Fall back to
build.testfrom.ai/config.yaml - Fall back to common patterns: Maven →
mvn test -pl <module>, npm →npm test
Execute with a 5-minute timeout. Parse output:
- Tests run / Passed / Failed / Errors / Skipped / Time elapsed
- For each failure: extract test name and assertion message (max 10 lines per failure)
Tests passed?
- yes — all tests pass (zero failures, zero errors) → go to "Review against plan"
- no — any test failure or error → go to "Mark blocked + present summary" with
{ status: "blocked", phase: "test", error: "<failure summary>" }
Review against plan
Use ultrathink for deep reasoning about correctness.
Get the diff: git diff for uncommitted changes, or git diff HEAD~1 if already committed. Read modified files in full for context.
Plan compliance: Do changes match the step's instructions? Are all Files: modified? Any extra files changed?
Convention check: Read .claude/rules/ and .github/instructions/ for relevant file types. Check naming, framework patterns, interface separation, template patterns, test patterns.
Bug check: Null pointer risks, resource leaks, hardcoded values that should be configurable, missing imports, property name mismatches.
Verdict: APPROVED, APPROVED WITH NOTES, or CHANGES REQUESTED.
Review passed?
- yes — verdict is APPROVED or APPROVED WITH NOTES → go to "Stage and commit"
- no — verdict is CHANGES REQUESTED → go to "Mark blocked + present summary" with
{ status: "blocked", phase: "review", error: "<list of required changes>" }
Stage and commit
Before anything else, read ../../shared/git-rules.md — all git/SCM conventions.
Branch check: Verify on feature/* or bugfix/* branch. If not, run bash .ai/lib/ensure-feature-branch.sh $SPEC_DIR.
Determine files: From the step's Files: list + git status for files clearly part of this step. Never stage unrelated files, .env, credentials, or secrets.
Stage specifically (never git add -A):
git add <file1> <file2> ... <implement.md>
Always include implement.md to capture the status update.
Commit message: Extract work item ID from spec directory name. Format: #<ID> <imperative description>. Use HEREDOC:
git commit -m "$(cat <<'EOF'
#<ID> <description>
EOF
)"
If nothing to stage, report "Nothing to stage — no commit created" and go to "Mark blocked + present summary" with { status: "blocked", phase: "commit", error: "nothing to stage" }.
Commit succeeded?
- yes — commit created with valid hash → go to "Mark done + present summary"
- no — commit failed → go to "Mark blocked + present summary" with
{ status: "blocked", phase: "commit", error: "<message>" }
Mark done + present summary
Update implement.md:
**Status:** done
Print:
## Step N complete: <step title>
**Files modified:** <list>
**Compilation:** passed
**Tests:** passed (<N> tests, <time>)
**Review:** <verdict>
**Commit:** `<short hash>` — `<commit message>`
**Next:** Step <N+1> — <title> (or "All steps done — run `/dx-pr`")
If $IN_STEP_LOOP == 0, add: "Run /dx-step for the next step, or /dx-step-all to continue autonomously." When a loop is driving you, omit it — the coordinator already continues.
Then end with the ## Return block (verdict: pass).
Mark blocked + present summary
Update implement.md:
**Status:** blocked
Include the phase, error category, message, and suggested action:
{ status: "blocked", phase: "compile|test|review|commit", error: "<message>" }
Print the summary with the failure details, then end with the ## Return block (verdict: fail, the phase and error in summary). The coordinator (dx-step-all) branches on that verdict to decide whether to call dx-step-fix.
Success Criteria
- [ ] Target step status updated: pending → done (or blocked with reason)
- [ ] If done: compilation/build command exits 0
- [ ] If done: tests pass (zero failures)
- [ ] If done: review verdict is APPROVED or APPROVED WITH NOTES
- [ ] If done: commit created with work item ID in message
- [ ] If done: files modified match step's
**Files:**list - [ ] implement.md updated in-place (no corruption of other steps)
Examples
Execute next step (full pipeline)
/dx-step 2435084
Finds the first pending step in implement.md, marks it in-progress, implements code, verifies compilation, runs tests, reviews against plan and conventions, commits, and marks done.
Resume interrupted step
/dx-step 2435084
If a step is in-progress (from a previous interrupted run), resumes it instead of starting the next pending step.
All steps complete
/dx-step 2435084
If no pending steps remain, prints "All steps are done. Run /dx-pr to create a pull request."
Troubleshooting
Step marked blocked after compilation failure
Cause: The implemented code doesn't compile, and the one auto-fix attempt also failed.
Fix: Run /dx-step-fix to diagnose and fix the error, or manually fix and reset the status to pending in implement.md.
Step marked blocked after test failure
Cause: Tests fail after implementation.
Fix: Run /dx-step-fix to diagnose and fix failures, then reset status to pending.
Step marked blocked after review
Cause: Code review found issues (convention violations, bugs, plan deviations).
Fix: Run /dx-step-fix to address the required changes, then reset status to pending.
Step creates a new helper instead of reusing existing one
Cause: The step instructions in implement.md say "create new" when an existing utility would work.
Fix: Fix implement.md first — update the step's What instructions to reference the existing code. Then re-run /dx-step.
"No implement.md found"
Cause: Planning hasn't been done yet.
Fix: Run /dx-plan <id> to generate the implementation plan first.
"Not on a feature branch"
Cause: Working on development, main, or another protected branch.
Fix: The skill auto-runs ensure-feature-branch.sh. If that fails, manually create: git checkout -b feature/<id>-<slug>.
Decision Examples
Fixable Error (VALIDATION)
Error: error TS2304: Cannot find name 'HeroProps'
Classification: VALIDATION / SYNTAX — missing import
Action: Add import { HeroProps } from './hero.types', re-run compilation
Outcome: Fixed. Proceed to tests.
Unfixable Error (PERMANENT)
Error: bash: mvn: command not found
Classification: PERMANENT / MISSING_DEPENDENCY
Action: Do NOT attempt fix. Mark step blocked: "Maven not installed on this machine."
Ambiguous Error (needs classification)
Error: ECONNREFUSED 127.0.0.1:4502
Classification: TRANSIENT / TIMEOUT — AEM is not running
Action: Retry once (AEM may be starting). If still failing → mark blocked: "AEM instance not available."
Test Failure
Tests: 3 failed out of 47
Action: Mark blocked with { status: "blocked", phase: "test", error: "3 test failures: TestDialog#testDropdown, ..." }. Coordinator calls /dx-step-fix.
Review Rejection
Verdict: CHANGES REQUESTED — hardcoded color #FF0000 should use SCSS variable
Action: Mark blocked with { status: "blocked", phase: "review", error: "Convention violation: use $primary-color instead of #FF0000" }. Coordinator calls /dx-step-fix.
Anti-Rationalization
Common excuses for cutting corners during step execution — and why they're wrong:
| False Logic | Reality Check |
|---|---|
| "I'll test at the end" | Bugs cascade — a Step 1 error corrupts Steps 2-5. Test every step. |
| "This is too small to commit separately" | Small commits are costless; large ones hide problems and block bisection. |
| "I know what this file does, no need to read it" | Assumptions cause wrong edits. Reading is cheap, debugging is expensive. |
| "I'll skip the review — it compiled and tests pass" | Compilation proves syntax, not correctness. Reviews catch logic bugs. |
| "The plan is wrong, I'll improvise a better approach" | Mark the step blocked and let the user decide. Don't freelance. |
| "I'll refactor this adjacent code while I'm here" | Scope creep causes merge conflicts and breaks unrelated tests. Touch only what the step requires. |
| "Tests pass immediately, so they're fine" | A test that passes before implementation proves nothing — fix it. |
Rules
- One step at a time — execute exactly one step, then end with the
## Returnblock. The coordinator or user decides what's next. - Read before writing — always read a file before editing it. Never blindly edit.
- Follow conventions — read
.claude/rules/and.github/instructions/(if it exists) for the relevant file types before writing code. For AEM modal/overlay work, also checkshared/aem-dom-rules.md. - Don't improvise — implement exactly what the step says. If instructions are unclear, mark the step blocked with a note rather than guessing.
- Update status immediately — mark in-progress before starting, done/blocked when finished. This is the state machine that coordinators rely on.
- Compile check is mandatory — never mark a step done without verifying compilation passes.
- Tests are mandatory — never mark a step done without running tests.
- Review is mandatory — never mark a step done without reviewing against the plan.
- Commit is mandatory — never mark a step done without committing changes.
- Follow git-rules.md — read
../../shared/git-rules.mdbefore committing. Stage specifically, nevergit add -A. - No empty commits — if nothing to stage, report and mark blocked.
Return
This skill runs in a forked context. It MUST end with a ## Return block per plugins/dx-core/shared/skill-return-contract.md — in both the standalone and the step-loop case.
verdict: pass— step committed and markeddone(or no pending steps remain)verdict: fail— step markedblocked;summarynames the phase (compile|test|review|commit) and the error
Examples:
## Return
verdict: pass
summary: Step 3 done — Add dialog fields; committed 4bf6fe5; 12 tests passed; review APPROVED.
artifacts:
- .ai/specs/2490722-microsite/implement.md
- .ai/specs/2490722-microsite/dev-all-progress.md
next_action: next pending step is 4 — Wire the model
## Return
verdict: fail
summary: Step 3 blocked in phase test — 2 failures in HeroModelTest (null title).
artifacts:
- .ai/specs/2490722-microsite/implement.md
next_action: run /dx-step-fix
04 同仓库更多 Skills
dx-hub-status
Show hub dispatch status — which repos are running, done, blocked or failed. Use for 'hub status', 'what's running'.
dx-hub-init
Initialize a hub directory for multi-repo orchestration. Discovers sibling repos, merges configs, validates CLI compatibility. Use when setting up hub mode for the first time. Trigger on "init hub", "set up hub", "multi-repo setup".
dx-hub-dispatch
Dispatch a ticket to several repos — open an independent Claude session per repo in VS Code terminals. Use for 'hub dispatch', 'work on ticket across repos'.
dx-hub-config
View and edit hub configuration — add repos, adjust terminal delay. Use to manage hub settings. Trigger on "hub config", "add repo to hub", "terminal delay".
dx-discover-repos
Resolve which repos a work item touches (explicit directive → simple block → cross-repo table → LLM). Used by the KAI-HUB router to fan an agent out across repos; 'which repos'.
dx-upgrade
Upgrade a consumer project to the installed plugin versions — run dx-doctor, fix stale and missing files, list manual actions. Use after upgrading plugins.