| name | dev-pipeline |
| description | Mercury's preset Main → Dev → Acceptance chain for executing a single, well-scoped coding task end-to-end with blind acceptance review. Use this skill when the user says "dev pipeline", "dispatch task", "派发任务", "dev → acceptance", "跑完整开发流程", "dev pipeline 验证", "blind review", "完整开发链", or when a task is ready to be implemented and verified by separate agents (instead of doing it inline). The skill spawns the dev subagent to implement, then spawns the acceptance subagent to blind-review the result, then loops or completes based on the verdict. Independent of Mercury's other modules — works in any repo that has .claude/agents/dev.md + .claude/agents/acceptance.md defined.
|
| user-invocable | true |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash, Agent, WebSearch, WebFetch |
Dev Pipeline — Main → Dev → Acceptance Preset Chain
A linear, single-task pipeline. The Main agent (you, the orchestrator running this skill) coordinates two sub-agent invocations and decides loopback vs completion.
Why a preset, not dynamic orchestration? See PHILOSOPHY.md in this directory.
Prerequisites
Before invoking this skill, the following must be true:
- Agents discoverable: .claude/agents/dev.md and .claude/agents/acceptance.md exist with valid YAML frontmatter (name dev / name acceptance). Verify by running the
claude agents command or by inspecting the files directly. If they do not exist, this skill cannot run — fall back to inline implementation.
- Task is well-scoped: clear definition of done, bounded write scope, listed acceptance criteria. If the task is ambiguous, run a research/design pass first instead of dispatching dev.
- Branch is correct: you are on a feature branch (not develop or master). Dev agent will commit and push to whatever branch is current.
- Issue exists: every task must have a GitHub Issue (Mercury rule). PR will reference it via Closes #N.
Iron Rules
| Rule | Why |
|---|
| One task per pipeline run | Mercury's preset is linear single-task, not parallel multi-task. For parallelism, the user opens multiple sessions. |
| TaskBundle is inline JSON, not Obsidian | This skill is dependency-free. The Memory Layer / Obsidian KB integration ships in Phase 3 — until then, the bundle is constructed inline by Main and passed to the dev subagent in the prompt. |
| Acceptance is blind | The acceptance subagent MUST NOT receive the dev subagent's reasoning, narrative, self-assessment, or risk evaluation. It receives only the AcceptanceBundle (criteria) plus a blindReceipt containing changed-file paths and test results. |
| Max 3 dev iterations | If acceptance returns fail 3 times, escalate to user — do not loop forever. |
| Main does not write code | Main coordinates, reviews receipts, decides next action. Implementation belongs to dev. Verification belongs to acceptance. |
| Sub-agents cannot spawn sub-agents | Per Claude Code documented constraint. Only the Main thread (running this skill) can dispatch dev or acceptance. Dev cannot call acceptance directly. |
Phase 1: Build TaskBundle
MANDATORY before any dispatch. Main constructs the TaskBundle inline based on the user's request, the GitHub Issue body, and any referenced design docs.
{
"taskId": "<short-slug>",
"issue": "<owner/repo#N>",
"title": "<one-line summary>",
"context": "<2-5 sentences why this task exists>",
"definitionOfDone": [
"<verifiable criterion 1>",
"<verifiable criterion 2>"
],
"allowedWriteScope": [
"<file or glob 1>",
"<file or glob 2>"
],
"mustNotTouch": [
"<file or glob>"
],
"readScope": [
"<file paths the dev should read first>"
],
"acceptanceCriteria": [
"<what acceptance will check 1>",
"<what acceptance will check 2>"
],
"verifyCommands": [
"<exact bash command to validate, e.g. pnpm test packages/foo>"
]
}
Gate: every field non-empty. If definitionOfDone contains a subjective phrase (clean, elegant, good), rewrite it as a measurable criterion or escalate to the user.
Phase 2: Dispatch Dev
Before dispatching, capture the task-start SHA so Phase 3 can compute the diff range correctly (do not rely on HEAD~1). Store it OUTSIDE the working tree to avoid repo pollution:
TASK_START_SHA=$(git rev-parse HEAD)
BRANCH_KEY=$(git rev-parse --abbrev-ref HEAD | tr '/' '_' | tr -cd '[:alnum:]_-')
SHA_FILE="${TMPDIR:-/tmp}/dev-pipeline-task-start-sha-${BRANCH_KEY}"
echo "$TASK_START_SHA" > "$SHA_FILE"
The file is keyed by the current branch name (slash-sanitized). This is stable across Bash invocations within the same pipeline run, and concurrent pipelines collide only if they are on the same branch — which would be a pre-existing git conflict anyway. Phase 6 hand-off must remove it.
Use the Agent tool with subagent_type set to dev. The prompt template:
You are operating under the dev agent role (.claude/agents/dev.md). Implement the following task and return a JSON receipt as your final message.
## TaskBundle
[paste TaskBundle JSON built in Phase 1]
## Execution Protocol
1. Read every file listed in readScope.
2. Implement within allowedWriteScope only. Touching anything in mustNotTouch is forbidden.
3. Run every command in verifyCommands. ALL must pass before you commit.
4. Self-fix once if a verifyCommand fails. If it still fails, STOP and report — do NOT commit broken code.
5. Commit with format type(scope): summary (Mercury convention).
6. Push to current branch.
7. Output the JSON receipt below as your FINAL message.
## Receipt template
{
"taskId": "[copied out of the bundle]",
"status": "completed|blocked|escalated",
"changedFiles": ["path", "..."],
"commitSha": "sha",
"verifyResults": [
{"command": "cmd", "exitCode": 0, "summary": "one line"}
],
"evidence": "file:line citations supporting definition-of-done",
"risks": "known risks or follow-up needed",
"escalationReason": "only if status is not completed"
}
## Forbidden
- git switch, git checkout, git branch, git reset, git rebase, git merge, git push --force
- git add -A or git add .
- Modifying CLAUDE.md or any file under .claude/agents/
- Picking up additional work after the receipt is filed
Gate: dev must return a JSON receipt with status completed. If blocked or escalated, jump to Phase 5 (escalate to user).
Phase 3: Receipt Review (Main)
Main checks receipt completeness — NOT correctness (that is acceptance's job).
Checklist:
Gate: if any check fails, send a correction prompt to dev (still iteration 1) with the specific deficiency. Do not advance to acceptance with an incomplete receipt.
Phase 4: Dispatch Acceptance (BLIND)
Build the blindReceipt by stripping dev's narrative fields. Preserve original JSON types — changedFiles and verifyResults are arrays in the dev receipt and MUST remain arrays here, not stringified placeholders:
{
"taskId": "task-slug",
"changedFiles": ["path/to/file1.ts", "path/to/file2.ts"],
"commitSha": "abc123def",
"verifyResults": [
{"command": "pnpm test packages/foo", "exitCode": 0, "summary": "12 passed"},
{"command": "pnpm lint", "exitCode": 0, "summary": "0 issues"}
]
}
Note what was REMOVED relative to the dev receipt: evidence, risks, escalationReason. The acceptance agent must form its own conclusions out of code and tests, not out of dev's self-assessment.
Build the AcceptanceBundle (also preserve original types — definitionOfDone, acceptanceCriteria, verifyCommands are arrays, not strings):
{
"taskId": "task-slug",
"title": "one-line summary",
"definitionOfDone": ["criterion 1", "criterion 2"],
"acceptanceCriteria": ["check 1", "check 2"],
"verifyCommands": ["pnpm test packages/foo", "pnpm lint"]
}
Use the Agent tool with subagent_type set to acceptance. Prompt template:
You are operating under the acceptance agent role (.claude/agents/acceptance.md). BLIND REVIEW: you are FORBIDDEN from inferring or asking about the dev agent's reasoning, narrative, or self-assessment.
## AcceptanceBundle
[paste AcceptanceBundle JSON]
## Blind Receipt (changed files only — NO dev narrative)
[paste blindReceipt JSON]
## Instructions
1. Read every file listed in changedFiles at the latest commit.
2. Run every command in verifyCommands. Capture exit codes and output.
3. Evaluate each acceptanceCriteria and definitionOfDone item against the actual code and runtime output. Cite file:line evidence.
4. Output your verdict as JSON.
## Verdict template
{
"verdict": "pass|partial|fail|blocked",
"criteriaResults": [
{"criterion": "text", "verdict": "pass|fail|partial", "evidence": "file:line or test output"}
],
"findings": ["problem 1", "problem 2"],
"recommendations": ["actionable fix 1"]
}
Gate: capture the verdict.
Phase 5: Decide Next Action
Based on the acceptance verdict:
| Verdict | Action |
|---|
| pass | Pipeline complete. Summarize result for user (Chinese for milestones). Hand off to /pr-flow if a PR is the next step. Run cleanup (see below). |
| partial | Re-dispatch dev with the original full TaskBundle plus a priorFindings array containing acceptance's findings. Constraints (definitionOfDone, allowedWriteScope, mustNotTouch, readScope) MUST be carried over verbatim from iteration 1 — never widened, never dropped. Increment iteration. Do NOT clean up $SHA_FILE between iterations — Phase 3 needs it on every retry. |
| fail | Same as partial: dispatch with full original TaskBundle + priorFindings + priorRecommendations. Constraints carried verbatim. Increment iteration. Do NOT clean up between iterations. |
| blocked | Escalate to user. Acceptance hit an environmental block; user must resolve. Run cleanup. |
Constraint preservation: every retry dispatch must include the EXACT original definitionOfDone, allowedWriteScope, mustNotTouch, and readScope from iteration 1. Adding a new constraint is OK; widening or dropping an existing one is forbidden — that defeats the purpose of the bundle as a contract.
Iteration cap: if iteration is at least 3 and verdict is still not pass, escalate to user with the full history and run cleanup. Do not silently keep looping.
Cleanup (mandatory on every terminal exit path)
rm -f "$SHA_FILE"
This runs on pass, blocked, escalation after partial/fail, and on iteration-cap escalation. The ONLY paths that skip cleanup are intra-iteration dev re-dispatches (because Phase 3 still needs the SHA). If the loop terminates without reaching one of these branches (e.g. host crash), the file at ${TMPDIR:-/tmp}/dev-pipeline-task-start-sha-$$ will be cleaned up by OS tmp eviction; PID-suffix prevents collision.
Phase 6: Hand-off
Phase 6 is reached only on pass. Cleanup for non-pass terminal exits is handled inside Phase 5 — do not duplicate it here.
On pass:
- Confirm commit is pushed (
git status)
- If user requested PR: invoke
/pr-flow
- Mark the related GitHub Project item Done via
Closes #N in the merged PR (GitHub auto-moves linked Issues on merge)
- Summarize in Chinese for the user
- Run the Phase 5 Cleanup block (
rm -f "$SHA_FILE") as the final action
Single source of truth: the Phase 5 Cleanup block is the only authoritative description of when $SHA_FILE is removed. Phase 6 only reaches it via the pass branch above. If you find yourself debating "should I clean up here", re-read Phase 5.
Detachability
This skill is designed to be portable to any repository that uses GitHub + Claude Code, provided:
- .claude/agents/dev.md and .claude/agents/acceptance.md exist with valid frontmatter
- The target repo uses GitHub Issues + GitHub PRs (the protocol references
Closes #N, gh pr create, and Mercury's /pr-flow skill — all GitHub-specific). Non-GitHub repos would need protocol adaptation.
- The repo has a sane verifyCommands story (tests, lint, build commands that exit non-zero on failure)
- The user is on a feature branch (not main, develop, or master)
This Argus copy has already been stripped of the Mercury-specific /gh-project-flow reference — Phase 6 step 3 uses only native Closes #N auto-move, which works for any GitHub repo. No Mercury dependency remains.
Known Limitations
- No parallel tasks. By design — Mercury's preset chain is linear single-task. For parallelism, open another session.
- No persistent memory between invocations. Each pipeline run is fresh. Phase 3 Memory Layer will lift this constraint.
- Subagent context is independent. The dev and acceptance subagents do NOT see the main session's history — only the prompt you send them. Be explicit; do not assume shared context.
- Critic agent not included by default. If you want a third independent verification pass (different model), add a Phase 4.5 dispatch to subagent_type critic. Out of scope for the baseline pipeline.
Failure Modes
| Symptom | Likely Cause | Fix |
|---|
| Agent tool returns unknown subagent type dev | Frontmatter missing or invalid in .claude/agents/dev.md | Check that name dev is the first non-divider line; restart session |
| Dev commits files outside allowedWriteScope | Bundle scope was too vague, or dev hallucinated needed files | Tighten scope; if hallucination, fix and re-dispatch with explicit prohibition |
| Acceptance returns pass but obvious bug exists | Acceptance criteria did not cover the bug class | Update bundle criteria; this is a design failure of the bundle, not the agent |
| Pipeline loops 3+ times on the same finding | Dev keeps fixing the wrong thing | Escalate immediately; usually means the finding text is ambiguous |