auto-dev
npx skills add https://github.com/grnfromdark/autodevskill --skill auto-dev
Agent 安装分布
Skill 文档
Autodev Pipeline Generator
Overview
This skill generates a complete Autodev automated development pipeline from a structured todolist.md file. The output is a self-contained directory that runs autodev.sh to drive Claude Code through a gated, TDD-enforced, card-by-card development workflow â fully automated, no human in the loop.
Trigger phrases: “帮æçæ xxx ç autodev æä»¶”, “create autodev for”, “generate autodev pipeline”
What is Autodev?
Autodev is a spec-anchored, gate-guarded, TDD-enforced automated development methodology. It:
- Splits a task list into sequential Task Cards (one AI session per card)
- Enforces TDD 5-step closure per card (RED â GREEN â SPEC â LINT â GATE)
- Runs automated gate checks between phases
- Auto-repairs test failures (up to 3 retries per card)
- Tracks progress in a state file for resumable execution
- Independent acceptance verification per card (separate AI verifies ACs)
- AI mutual review for high-risk decisions (SPEC-DECISION / AI-REVIEW / AI-GATE ä¸çº§)
- Decision audit trail (
decisions.jsonl) for cross-card traceability - Pipeline completion summary â auto-generates structured report: what was implemented, files changed, decisions made, test results
Checklist
You MUST complete these steps in order:
- Read the todolist â understand groups, tasks, phases, dependencies, test commands
- Gather project context â identify spec doc, source files, test paths, key constraints
- Design the pipeline â map todolist groups â phases â cards, define gate checks
- Generate all files â autodev.sh, system_prompt.md, gate_check.sh, cards/*.md, phase_gate.md, state, decisions.jsonl
- Verify â dry-run the script, confirm all card files exist, paths resolve correctly
Step 1: Read the Todolist
Read the todolist.md file completely. Extract:
| Item | What to look for |
|---|---|
| Groups | Top-level sections (Group 1, Group 2…) â these become Phases |
| Tasks | Individual numbered items within groups â these become Cards (or get merged into Cards) |
| Dependencies | Which tasks depend on others â determines Card ordering |
| Execution phases | If the todolist defines phases (Phase A, B, C…) â use them directly |
| Test commands | How to run tests â becomes the test verification step |
| Key constraints | Backward compatibility, safety rules, P1 fixes â become system_prompt constraints |
| Source files | Which files are being modified â becomes Card “read existing code” sections |
| Spec/design docs | Referenced design documents â becomes the “single source of truth” |
Step 2: Gather Project Context
Resolve context autonomously (no human confirmation in runtime):
1. What is the spec/design document path?
â This is the "single source of truth" referenced by all cards
2. What is the test command?
â e.g., "python3 -m pytest tests/test_foo.py -q" or "npm test"
3. What are the core source files being modified?
â Listed in system_prompt as "project files"
4. What are the project-specific constraints?
â e.g., "backward compatible", "no breaking changes", "é纲ä¸è´æ§"
5. Where should the Autodev directory live?
â Convention: Autodev/{project_name}/
6. If anything is unclear, how should ambiguity be resolved?
â Infer from repo evidence (todolist, spec, tests, git history, existing patterns),
choose the most conservative backward-compatible option, and record assumptions in
system_prompt.md ("Assumptions & Defaults"). Do NOT block for user confirmation.
Step 3: Design the Pipeline
Mapping Groups to Phases
Each Group in the todolist becomes a Phase. Each Phase ends with a GATE.
Group 1 â Phase A â GATE:A
Group 2 â Phase B â GATE:B
...
Last Group â Phase N â GATE:FINAL
Mapping Tasks to Cards
Merge small related tasks into single Cards. Keep complex tasks as their own Card. Target: 2-5 tasks per Card, 3-7 Cards per Phase.
Heuristics for merging:
- Same source file â merge
- Sequential dependency with no external dependency â merge
- Total estimated complexity < 1 Claude session â merge
Heuristics for splitting:
- Different source files â separate
- Independent testable unit â separate
- High complexity (e.g., “MC simulation core”) â own Card
Card ID scheme
Use {Phase}.{Sequence} format:
- Alphanumeric phases: A.1, A.2, B.1, C.1
- Numeric phases: 0.1, 0.2, 1.1, 2.1
Adding verification Cards
Add a verification Card at the end of each Phase (before the GATE) that:
- Runs all tests for that phase
- Checks test coverage against the todolist
- Runs full regression
Gate checks
Design gate_check.sh with:
- Universal checks (always include):
- Unit tests pass
- Full regression tests pass
- SPEC-DECISION audit (grep for AI decisions)
- Project-specific checks (customize):
- Backward compatibility verification
- Contract/interface checks
- Config consistency
- Import validation
Step 4: Generate All Files
Directory Structure
Autodev/{project_name}/
âââ autodev.sh # Main pipeline script
âââ system_prompt.md # AI session prompt
âââ gate_check.sh # Automated gate checks
âââ state # Progress tracker (empty file)
âââ decisions.jsonl # Decision audit trail (empty file, runtime populated)
âââ logs/ # Runtime logs (empty dir)
âââ cards/
âââ {A.1}.md # Task cards
âââ {A.2}.md
âââ ...
âââ phase_gate.md # Phase gate audit template
summary.md is a runtime artifact. Do NOT pre-create it during scaffolding.
File Templates
autodev.sh Template
#!/bin/bash
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
# {PROJECT_DISPLAY_NAME} â Automated Development Pipeline
# ç¨æ³: ./{AUTODEV_PATH}/autodev.sh [OPTIONS]
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
set -euo pipefail
# ââââ è·¯å¾é
ç½® ââââ
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
AUTODEV="$SCRIPT_DIR"
CARDS_DIR="$AUTODEV/cards"
LOGS_DIR="$AUTODEV/logs"
STATE_FILE="$AUTODEV/state"
SYSTEM_PROMPT="$AUTODEV/system_prompt.md"
GATE_SCRIPT="$AUTODEV/gate_check.sh"
# ââââ macOS å
¼å®¹ ââââ
if command -v gtimeout &>/dev/null; then
TIMEOUT_CMD="gtimeout"
elif command -v timeout &>/dev/null; then
TIMEOUT_CMD="timeout"
else
TIMEOUT_CMD=""
fi
# ââââ é
ç½® ââââ
MODEL="${{ENV_PREFIX}_MODEL:-opus}"
VERIFY_MODEL="${{ENV_PREFIX}_VERIFY_MODEL:-haiku}" # éªæ¶éªè¯ç¨è½»é模å
CARD_TIMEOUT="${{ENV_PREFIX}_TIMEOUT:-900}"
GATE_MAX_RETRIES="${{ENV_PREFIX}_GATE_RETRIES:-3}"
AC_MAX_RETRIES="${{ENV_PREFIX}_AC_RETRIES:-3}" # ç¬ç«éªæ¶æå¤èªä¿®å¤è½®æ¬¡
DECISIONS_CONTEXT_LINES="${{ENV_PREFIX}_DECISIONS_CONTEXT_LINES:-120}"
DECISIONS_FILE="$AUTODEV/decisions.jsonl" # å³ç审计追踪
PHASE_BASELINE_FILE="$AUTODEV/.phase_baseline" # æ¯ä¸ª Phase ç diff åºçº¿
SUMMARY_FILE="$AUTODEV/summary.md" # Pipeline 宿æ»ç»
# ââââ æ§è¡é¡ºåº ââââ
ALL_STEPS=(
{ALL_STEPS_CONTENT}
)
# ââââ é¢è²è¾åº ââââ
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_ok() { echo -e "${GREEN}[OK ]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; }
log_title() {
echo ""
echo -e "${BOLD}${CYAN}=================================================${NC}"
echo -e "${BOLD}${CYAN} $1${NC}"
echo -e "${BOLD}${CYAN}=================================================${NC}"
}
# ââââ è¿åº¦ç®¡ç (100% éç¨ï¼ä¸æ¹) ââââ
is_completed() { grep -qxF "$1" "$STATE_FILE" 2>/dev/null; }
mark_completed() { echo "$1" >> "$STATE_FILE"; log_ok "宿: $1"; }
get_completed_count() {
if [ -f "$STATE_FILE" ]; then wc -l < "$STATE_FILE" | tr -d ' '
else echo "0"; fi
}
get_next_card_before_gate() {
local gate_phase=$1 last_card=""
for step in "${ALL_STEPS[@]}"; do
local type="${step%%:*}" id="${step#*:}"
if [ "$type" = "CARD" ]; then last_card="$id"
elif [ "$type" = "GATE" ] && [ "$id" = "$gate_phase" ]; then break; fi
done
echo "${last_card:-{FIRST_CARD_ID}}"
}
# ââââ æå»º Prompt ââââ
build_prompt() {
local card_file="$CARDS_DIR/${1}.md"
[ ! -f "$card_file" ] && { log_fail "Card æä»¶ä¸åå¨: $card_file"; return 1; }
{
cat "$SYSTEM_PROMPT"; echo ""; echo "---"; echo ""
echo "## è¿è¡æ¶ä¿¡æ¯"
echo "AUTODEV_DIR: $AUTODEV"
echo "DECISIONS_FILE: $DECISIONS_FILE"
echo ""
echo "## å½åè¿åº¦"
if [ -f "$STATE_FILE" ] && [ -s "$STATE_FILE" ]; then
echo "已宿ç Card:"; cat "$STATE_FILE" | sed 's/^/- /'
else echo "å°æ 已宿ç Cardï¼é¦ä¸ªä»»å¡ï¼"; fi
# 注å
¥ååºå³çä¸ä¸æ
if [ -f "$DECISIONS_FILE" ] && [ -s "$DECISIONS_FILE" ]; then
echo ""; echo "## ååºå³çè®°å½ï¼æè¿ ${DECISIONS_CONTEXT_LINES} æ¡ï¼"
echo '```jsonl'; tail -n "$DECISIONS_CONTEXT_LINES" "$DECISIONS_FILE"; echo '```'
fi
echo ""; echo "---"; echo ""; cat "$card_file"
}
}
# ââââ æ§è¡åå¼ Card (éç¨éª¨æ¶ï¼TEST_CMD å¯å®å¶) ââââ
execute_card() {
local card_id=$1 timestamp=$(date +%Y%m%d_%H%M%S)
local log_file="$LOGS_DIR/card_${card_id//./_}_${timestamp}.log"
log_title "Card $card_id"
local prompt; prompt="$(build_prompt "$card_id")" || return 1
log_info "Model: $MODEL | Timeout: ${CARD_TIMEOUT}s"
log_info "Log: $log_file"; echo ""
cd "$PROJECT_ROOT"
local exit_code=0
if [ -n "$TIMEOUT_CMD" ]; then
$TIMEOUT_CMD "$CARD_TIMEOUT" bash -c \
"echo \"\$1\" | claude -p --dangerously-skip-permissions --model \"\$2\" --verbose 2>&1" \
-- "$prompt" "$MODEL" | tee "$log_file" || exit_code=$?
else
bash -c \
"echo \"\$1\" | claude -p --dangerously-skip-permissions --model \"\$2\" --verbose 2>&1" \
-- "$prompt" "$MODEL" | tee "$log_file" || exit_code=$?
fi
[ $exit_code -eq 124 ] && { log_fail "Card $card_id è¶
æ¶ (>${CARD_TIMEOUT}s)"; return 1; }
[ $exit_code -ne 0 ] && { log_fail "Card $card_id æ§è¡å¤±è´¥ (exit: $exit_code)"; return 1; }
# æµè¯éªè¯ + èªå¨ä¿®å¤å¾ªç¯
echo ""
local test_attempt=0 tests_passed=false
while [ $test_attempt -lt $GATE_MAX_RETRIES ]; do
test_attempt=$((test_attempt + 1))
log_info "è¿è¡æµè¯ (第 ${test_attempt}/${GATE_MAX_RETRIES} 次)..."
cd "$PROJECT_ROOT"
local test_output
test_output=$({TEST_CMD} 2>&1) && tests_passed=true
echo "$test_output" | tee -a "$log_file"
[ "$tests_passed" = true ] && { log_ok "æµè¯éè¿"; break; }
if [ $test_attempt -lt $GATE_MAX_RETRIES ]; then
log_warn "æµè¯å¤±è´¥ï¼AI èªå¨ä¿®å¤ ($test_attempt/$GATE_MAX_RETRIES)..."
local fix_prompt="Card $card_id æ§è¡åæµè¯å¤±è´¥ï¼è¯·ä¿®å¤ã
## æµè¯è¾åº
\`\`\`
$test_output
\`\`\`
## è§å
- 读åå¤±è´¥çæµè¯æä»¶å对åºçå®ç°ä»£ç
- 读åè®¾è®¡ææ¡£ç¡®è®¤æ£ç¡®è¡ä¸º
- ä¿®å¤åè¿è¡: {TEST_CMD}
- åªä¿®å¤å¯¼è´æµè¯å¤±è´¥çé®é¢ï¼ä¸è¦åé¢å¤æ¹å¨
- ä¸è½ç ´åç°ææµè¯ï¼ååå
¼å®¹ï¼"
cd "$PROJECT_ROOT"
echo "$fix_prompt" | claude -p --dangerously-skip-permissions --model "$MODEL" --verbose 2>&1 | tee -a "$log_file" || true
fi
done
[ "$tests_passed" != true ] && { log_fail "Card $card_id æµè¯ä¿®å¤å¤±è´¥"; return 1; }
# ââââ ç¬ç«éªæ¶éªè¯ + èªå¨ä¿®å¤éç¯ (Acceptance Verifier) ââââ
local card_content
card_content=$(cat "$CARDS_DIR/${card_id}.md")
local ac_attempt=0 ac_passed=false
while [ $ac_attempt -lt $AC_MAX_RETRIES ]; do
ac_attempt=$((ac_attempt + 1))
log_info "å¯å¨ç¬ç«éªæ¶éªè¯ (第 ${ac_attempt}/${AC_MAX_RETRIES} 次)..."
local ac_prompt
ac_prompt="$(cat <<VERIFY_EOF
ä½ æ¯ç¬ç«éªæ¶å®¡è®¡åï¼ä¸æ¯å¼åè
ï¼ãéªè¯ Card $card_id çéªæ¶æ 忝å¦å
¨é¨æ»¡è¶³ã
## Card 宿´å
容
$card_content
## è¯·ä½ ï¼
1. 读å Card ä¸"读åå·²æä»£ç "ååºçæºæä»¶ï¼ç¡®è®¤ä¿®æ¹å·²å°±ä½
2. è¿è¡ Card 䏿å®çæµè¯å½ä»¤ï¼ç¡®è®¤éè¿
3. éæ¡æ£æ¥éªæ¶æ åï¼AC-1, AC-2, ...ï¼ï¼å¤å® PASS æ FAIL
4. è¾åºæ ¼å¼ï¼ä¸¥æ ¼éµå®ï¼ï¼
AC-1: PASS â åå
AC-2: FAIL â åå
...
VERDICT: ALL_PASS | HAS_FAILURES
éè¦ï¼ä½ æ¯ç¬ç«å®¡è®¡åãç´æ¥è¯»æä»¶åè·æµè¯æ¥éªè¯ï¼ä¸è¦ä¿¡ä»»ä¹åç AI è¾åºã
VERIFY_EOF
)"
local verify_output verify_exit=0
verify_output=$(echo "$ac_prompt" | claude -p --dangerously-skip-permissions --model "$VERIFY_MODEL" --verbose 2>&1) || verify_exit=$?
echo "$verify_output" | tee -a "$log_file"
if [ $verify_exit -eq 0 ] && echo "$verify_output" | grep -q "VERDICT: ALL_PASS"; then
log_ok "éªæ¶éªè¯éè¿"
ac_passed=true
break
fi
if [ $verify_exit -ne 0 ]; then
log_warn "éªæ¶éªè¯ AI å¼å¸¸éåº (exit: $verify_exit)ï¼è§¦åèªæ¢å¤åéè¯"
else
log_warn "éªæ¶éªè¯åç°æªæ»¡è¶³ç ACï¼è§¦åä¿®å¤"
fi
local ac_fix_prompt
ac_fix_prompt="$(cat <<FIX_EOF
éªæ¶å®¡è®¡åç°ä»¥ä¸ AC æªæ»¡è¶³ï¼
$verify_output
è¯·ä¿®å¤æªéè¿çéªæ¶æ åãåªä¿®å¤æªéè¿ç项ï¼ä¸è¦æ¹å¨å·²éè¿çé¨åã
ä¿®å¤åè¿è¡æµè¯ç¡®è®¤éè¿ï¼å¹¶åå¤å次æ¥åç¬ç«éªæ¶ã
FIX_EOF
)"
echo "$ac_fix_prompt" | claude -p --dangerously-skip-permissions --model "$MODEL" --verbose 2>&1 | tee -a "$log_file"
# ä¿®å¤åéè·æµè¯ï¼å¤±è´¥åç»§ç»ä¸ä¸è½®èªä¿®å¤ï¼ä¸å
许带ç
éè¿
cd "$PROJECT_ROOT"
if ! {TEST_CMD} 2>&1 | tee -a "$log_file"; then
log_warn "Card $card_id éªæ¶ä¿®å¤åæµè¯ä»å¤±è´¥ï¼å°ç»§ç»èªå¨ä¿®å¤"
fi
done
[ "$ac_passed" != true ] && { log_fail "Card $card_id éªæ¶éªè¯æªéè¿ (è¾¾å° AC éè¯ä¸é)"; return 1; }
return 0
}
# ââââ Phase Gate ââââ
run_phase_gate() {
local phase=$1 timestamp=$(date +%Y%m%d_%H%M%S)
local log_file="$LOGS_DIR/gate_${phase}_${timestamp}.log"
log_title "Phase Gate: Phase $phase"
# 1. gate_check.sh + èªå¨ä¿®å¤å¾ªç¯
if [ -f "$GATE_SCRIPT" ]; then
local attempt=0 gate_passed=false
while [ $attempt -lt $GATE_MAX_RETRIES ]; do
attempt=$((attempt + 1))
log_info "é¨ç¦æ£æ¥ (第 ${attempt}/${GATE_MAX_RETRIES} 次)..."
cd "$PROJECT_ROOT"
local gate_output
gate_output=$(bash "$GATE_SCRIPT" 2>&1) && gate_passed=true
echo "$gate_output" | tee -a "$log_file"
[ "$gate_passed" = true ] && { log_ok "èªå¨é¨ç¦éè¿"; break; }
if [ $attempt -lt $GATE_MAX_RETRIES ]; then
log_warn "é¨ç¦æªéè¿ï¼AI èªå¨ä¿®å¤..."
local fix_prompt="é¨ç¦æ£æ¥æ¥åäºä»¥ä¸é®é¢ï¼è¯·ä¿®å¤:
$gate_output
读åè®¾è®¡ææ¡£åæµè¯ç¡®è®¤æ£ç¡®è¡ä¸ºãåªä¿®å¤é®é¢ï¼ä¸åé¢å¤æ¹å¨ã"
echo "$fix_prompt" | claude -p --dangerously-skip-permissions --model "$MODEL" --verbose 2>&1 | tee -a "$log_file" || true
fi
done
[ "$gate_passed" != true ] && { log_fail "é¨ç¦ç» $GATE_MAX_RETRIES 次修å¤ä»æªéè¿"; return 1; }
fi
# 2. AI 审计 (phase_gate.md)
log_info "è¿è¡ AI 审计..."
local gate_prompt
gate_prompt="$(cat "$CARDS_DIR/phase_gate.md")
---
å½å审计: Phase $phase
已宿ç Card:
$(grep "^CARD:" "$STATE_FILE" 2>/dev/null | sed 's/^CARD:/- /' || echo "ï¼æ ï¼")"
echo "$gate_prompt" | claude -p --dangerously-skip-permissions --model "$MODEL" --verbose 2>&1 | tee -a "$log_file" || true
log_ok "Phase Gate $phase 宿"
# 3. æ´æ° Phase åºçº¿ï¼ä¾ä¸ä¸é¶æ®µ phase-scoped diffï¼
git rev-parse HEAD > "$PHASE_BASELINE_FILE" 2>/dev/null || true
return 0
}
# ââââ Pipeline 宿æ»ç» ââââ
generate_summary() {
log_title "çæ Pipeline 宿æ»ç»"
local completed_cards
completed_cards=$(grep "^CARD:" "$STATE_FILE" 2>/dev/null | sed 's/CARD://' | tr '\n' ', ' | sed 's/,$//')
local completed_gates
completed_gates=$(grep "^GATE:" "$STATE_FILE" 2>/dev/null | sed 's/GATE://' | tr '\n' ', ' | sed 's/,$//')
# å¯¹æ¯ Pipeline å¯å¨æ¶ç baselineï¼å«å·²æäº¤ + æªæäº¤çå
¨é¨åæ´ï¼
local diff_ref="${PIPELINE_BASELINE:-HEAD}"
local git_diff_stat git_diff_files
cd "$PROJECT_ROOT"
git_diff_stat=$(git diff --stat "$diff_ref" 2>/dev/null || echo "(no git changes)")
# å·²æäº¤çåæ´ + æªæäº¤çåæ´
git_diff_files=$({ git diff --name-only "$diff_ref" 2>/dev/null; git diff --name-only 2>/dev/null; } | sort -u)
local decisions_content=""
if [ -f "$DECISIONS_FILE" ] && [ -s "$DECISIONS_FILE" ]; then
decisions_content=$(cat "$DECISIONS_FILE")
fi
local log_files
log_files=$(ls -1t "$LOGS_DIR"/*.log 2>/dev/null | head -20)
local summary_prompt
summary_prompt="$(cat <<SUMMARY_EOF
ä½ æ¯ Pipeline æ»ç»æ¥ååãè¯·æ ¹æ®ä»¥ä¸ä¿¡æ¯çæä¸ä»½ç»æåæ»ç»æ¥åï¼Markdown æ ¼å¼ï¼ã
## Pipeline ä¿¡æ¯
- 项ç®: {PROJECT_DISPLAY_NAME}
- 宿ç Cards: $completed_cards
- 宿ç Gates: $completed_gates
## Git åæ´ç»è®¡
\`\`\`
$git_diff_stat
\`\`\`
## åæ´çæä»¶å表
$git_diff_files
## å³çè®°å½
\`\`\`jsonl
$decisions_content
\`\`\`
## è¯·ä½ ï¼
1. 读åä¸è¿°åæ´çæä»¶ï¼çè§£æ¯ä¸ªæä»¶åäºä»ä¹ä¿®æ¹
2. çæä»¥ä¸æ ¼å¼çæ»ç»æ¥åï¼ç´æ¥è¾åº Markdown å
容ï¼ä¸éè¦ä»£ç åå
裹ï¼ï¼
# {PROJECT_DISPLAY_NAME} â Pipeline 宿æ»ç»
## å®ç°æ¦è¦
ï¼ç¨ 2-3 å¥è¯æ¦æ¬æ¬æ¬¡ pipeline å®ç°äºä»ä¹ï¼
## åæ´æ¸
å
| æä»¶ | åæ´ç±»å | 说æ |
|------|----------|------|
ï¼æ¯ä¸ªåæ´æä»¶ä¸è¡ï¼æ°å¢/ä¿®æ¹/å é¤ + ä¸å¥è¯è¯´æåäºä»ä¹ï¼
## å
³é®å³ç
ï¼ä» decisions.jsonl æåï¼å¦æ åå"æ "ï¼
- ãCard X.Yãå³çæè¿° â éæ©äºæ¹æ¡ Aï¼åå ...
## æµè¯ç»æ
ï¼ä» log æä»¶åæ¨æåªäº Card æ§è¡äºï¼æ´ä½ç»è®ºï¼
## 注æäºé¡¹
ï¼ä»»ä½æ®ä½é£é©ãTODOãæåç»å»ºè®®ï¼å¦æ åå"æ "ï¼
éè¦ï¼åªè¾åº Markdown æ¥åæ¬èº«ï¼ä¸è¦ç¨ä»£ç åå
裹ã
SUMMARY_EOF
)"
local summary_output
summary_output=$(echo "$summary_prompt" | claude -p --dangerously-skip-permissions --model "$VERIFY_MODEL" --verbose 2>&1) || true
# æå Markdown å
容åå
¥æä»¶
echo "$summary_output" > "$SUMMARY_FILE"
log_ok "æ»ç»æ¥åå·²çæ: $SUMMARY_FILE"
# å¨ç»ç«¯ç´æ¥å±ç¤ºæ»ç»
echo ""
echo -e "${BOLD}${CYAN}=================================================${NC}"
echo -e "${BOLD}${CYAN} Pipeline 宿æ»ç»${NC}"
echo -e "${BOLD}${CYAN}=================================================${NC}"
echo ""
cat "$SUMMARY_FILE"
echo ""
}
# ââââ CLI ââââ
show_help() {
echo "{PROJECT_DISPLAY_NAME} â Automated Development Pipeline"
echo ""
echo "ç¨æ³: ./{AUTODEV_PATH}/autodev.sh [OPTIONS]"
echo ""
echo "é项:"
echo " --from CARD_ID ä»æå® Card å¼å§ (å¦ --from B.1)"
echo " --model MODEL Claude 模å (é»è®¤: opus)"
echo " --reset æ¸
餿æè¿åº¦ï¼ä»å¤´å¼å§"
echo " --dry-run åªæ¾ç¤ºæ§è¡è®¡åï¼ä¸å®é
æ§è¡"
echo " --status æ¾ç¤ºå½åè¿åº¦"
echo " --help æ¾ç¤ºæ¤å¸®å©"
}
show_status() {
local total=${#ALL_STEPS[@]} done=$(get_completed_count)
echo ""; echo "{PROJECT_DISPLAY_NAME} å¼åè¿åº¦: $done / $total"; echo ""
for step in "${ALL_STEPS[@]}"; do
local id="${step#*:}" type="${step%%:*}"
if is_completed "$step"; then
echo -e " ${GREEN}[DONE]${NC} [$type] $id"
else
echo -e " ⬠[$type] $id"
fi
done
}
main() {
local start_from="" dry_run=false
while [[ $# -gt 0 ]]; do
case $1 in
--from) start_from="$2"; shift 2 ;;
--model) MODEL="$2"; shift 2 ;;
--reset) rm -f "$STATE_FILE"; log_info "è¿åº¦å·²æ¸
é¤"; shift ;;
--dry-run) dry_run=true; shift ;;
--status) show_status; exit 0 ;;
--help) show_help; exit 0 ;;
*) log_fail "æªç¥é项: $1"; show_help; exit 1 ;;
esac
done
mkdir -p "$LOGS_DIR"
touch "$STATE_FILE"
# è®°å½ Pipeline èµ·ç¹ï¼ç¨äºæç» summary diffï¼
PIPELINE_BASELINE=$(cd "$PROJECT_ROOT" && git rev-parse HEAD 2>/dev/null || echo "")
log_title "{PROJECT_DISPLAY_NAME} â Pipeline å¯å¨"
log_info "Model: $MODEL | Progress: $(get_completed_count)/${#ALL_STEPS[@]}"
if [ "$dry_run" = true ]; then
for step in "${ALL_STEPS[@]}"; do
local type="${step%%:*}" id="${step#*:}"
if is_completed "$step"; then
echo -e " ${GREEN}[SKIP]${NC} $type $id"
else
echo -e " ${YELLOW}[TODO]${NC} $type $id"
fi
done
exit 0
fi
local skip=false cards_executed=0 start_time=$(date +%s)
[ -n "$start_from" ] && skip=true
for step in "${ALL_STEPS[@]}"; do
local type="${step%%:*}" id="${step#*:}"
if [ "$skip" = true ]; then
[ "$id" = "$start_from" ] && skip=false || continue
fi
is_completed "$step" && { log_info "è·³è¿å·²å®æ: $type $id"; continue; }
if [ "$type" = "GATE" ]; then
run_phase_gate "$id" && mark_completed "$step" || { log_fail "Gate $id 失败"; exit 1; }
elif [ "$type" = "CARD" ]; then
execute_card "$id" && { mark_completed "$step"; cards_executed=$((cards_executed + 1)); } \
|| { log_fail "Card $id 失败ï¼éè·: ./{AUTODEV_PATH}/autodev.sh --from $id"; exit 1; }
fi
done
local elapsed=$(( ($(date +%s) - start_time) / 60 ))
generate_summary
log_title "Pipeline 宿ï¼Cards: $cards_executed | èæ¶: ${elapsed}m"
}
main "$@"
IMPORTANT: Do NOT use this template literally. Generate the FULL script with all functions expanded (like the real autodev.sh files). The template above shows the structure â the actual output must be a complete, runnable bash script.
system_prompt.md Template
Structure (customize content):
# {PROJECT_DISPLAY_NAME} â èªå¨å¼åä¼è¯
## ä½ çè§è²
ä½ æ¯ {PROJECT_NAME} çå¼åè
ãä¸¥æ ¼æç
§è®¾è®¡ææ¡£å®ç°ï¼ä¸æ·»å ææ¡£æªè¦æ±çåè½ã
## é¡¹ç®æä»¶
| æä»¶ | è·¯å¾ | ç¨é |
|------|------|------|
| **è®¾è®¡ææ¡£** | `{SPEC_PATH}` | å¯ä¸è®¾è®¡çç¸æº |
| **任塿¸
å** | `{TODOLIST_PATH}` | 详ç»ä»»å¡åè§£ |
{ADDITIONAL_FILES}
## TDD æµç¨
Step 1: RED â Step 2: GREEN â Step 3: SPEC â Step 4: LINT â Step 5: RUN
## æ ¸å¿çº¦æï¼ä» todolist ç P1/P2 ä¿®æ£ä¸æåï¼
{PROJECT_CONSTRAINTS}
## å³çåè®®ï¼æ 人å¼å®ç¯å¢ï¼
æ¬ä¼è¯æ 人类å¨åºãææéè¦"人类确认"çåºæ¯ï¼ç± **AI äºç¸ç¡®è®¤**æ¿ä»£ã
### Level 1: SPEC-DECISIONï¼èªå³ â ä½é£é©æ§ä¹ï¼
éç¨ï¼åæ°å½åã代ç 飿 ¼ãå°èå´å®ç°éæ©çä¸å½±åæ¶æçå³çã
Round 1: å举ææå¯è½æ¹æ¡ Round 2: æ¨æ¼æ¯ä¸ªæ¹æ¡çå½±å + ä¸ææ¡£å ¶ä»é¨åçä¸è´æ§ Round 3: éæ©æä¼æ¹æ¡ + æ æ³¨æ®ä½é£é©
å¨ä»£ç 䏿 注: `# SPEC-DECISION: chose B over A because ...`
### Level 2: AI-REVIEWï¼äºå®¡ â é«é£é©å³çï¼
éç¨ï¼æ¶æåæ´ãP1 约æç¸å
³ãååå
¼å®¹å½±åãè·¨æä»¶æ¥å£ä¿®æ¹ãè®¾è®¡ææ¡£æ§ä¹æå¤ç§åç解读ã
**è§¦åæ¡ä»¶**ï¼æ»¡è¶³ä»»ä¸å³è§¦å AI-REVIEW èé SPEC-DECISIONï¼ï¼
- æ¶å P1/P2 约æçå®ç°éæ©
- å½±å 2+ 个æä»¶çæ¥å£åæ´
- SPEC-DECISION Round 3 仿"é«"æ®ä½é£é©
- ä¿®æ¹å¯è½ç ´åç°ææµè¯æååå
¼å®¹æ§
**Review Agent ä¸ä¸å**ï¼æ ¹æ®è§¦ååå èªå¨éæ©å®¡è®¡è§è²ï¼
| 触ååå | 审计è§è² | 审æ¥éç¹ |
|---------|---------|---------|
| ååå
¼å®¹å½±å | **Compatibility Reviewer** | ç°æè°ç¨æ¹æ¯å¦ä¸åå½±åãé»è®¤å¼æ¯å¦ä¿æãå彿µè¯è¦ç |
| è·¨æä»¶æ¥å£åæ´ | **Interface Reviewer** | ç¾åä¸è´æ§ãç±»åå¹é
ãè°ç¨é¾å®æ´æ§ |
| P1/P2 约æç¸å
³ | **Constraint Reviewer** | çº¦ææ¯å¦è¢«æ»¡è¶³ãè¾¹çæ¡ä»¶ãéçº§è·¯å¾ |
| è®¾è®¡ææ¡£æ§ä¹ | **Spec Reviewer** | ææ¡£åç« èä¸è´æ§ãä¸å·²å®ç°ä»£ç çå¹é
度 |
**æ§è¡æ¹å¼**ï¼ä½¿ç¨ `Task` tool å¯å¨ä¸ä¸ªç¬ç«ç review agentï¼
Task(subagent_type=”general-purpose”, prompt=””” ä½ æ¯ {PROJECT_NAME} ç {REVIEWER_ROLE}ã请审æ¥ä»¥ä¸å³çï¼
å³çä¸ä¸æ
{æè¿°å½åé¢ä¸´çéæ©}
åéæ¹æ¡
A: {æ¹æ¡Aæè¿°} B: {æ¹æ¡Bæè¿°}
ç¸å ³çº¦æ
{ä» todolist/spec 䏿åç P1/P2 约æ}
è¯·ä½ ï¼
- 读å
{SPEC_PATH}ç¸å ³ç« èéªè¯ä¸¤ä¸ªæ¹æ¡çåè§æ§ - 读å
{TODOLIST_PATH}ç¡®è®¤ä»»å¡æå¾ - è¯»åæ¶åçæºæä»¶è¯ä¼°å½±åèå´
- ç»åºä½ çç¬ç«å¤æï¼éæ©åªä¸ªæ¹æ¡ + çç±
- å¦æä¸¤ä¸ªæ¹æ¡é½ä¸åéï¼æåºä½ çæ¹æ¡
- 对æ¯ä¸ªåç°æ 注严é级å«ï¼BLOCK / WARN / SUGGEST
严é级å«å®ä¹ï¼
- BLOCK: å¿ é¡»ä¿®æ¹æè½ç»§ç»ï¼è¿å P1 约ææç ´åç°æè¡ä¸º
- WARN: 建议修æ¹ï¼åå¨é£é©ä½ä¸è´å½ï¼å¯æ 注åè·³è¿
- SUGGEST: æ¹è¿å»ºè®®ï¼è®°å½ä½ä¸é»å¡æµç¨ “””)
**ç»æå¤ç**ï¼
- 两个 AI ä¸è´ â éç¨å
±è¯æ¹æ¡ï¼æ 注 `# AI-REVIEW: consensus on B`
- 两个 AI åæ§ â æä¸¥é级å«å¤çï¼
- åæ§é¡¹ä¸º BLOCK â éç¨**æ´ä¿å®**çæ¹æ¡ï¼æ 注 `# AI-REVIEW: disagreement/BLOCK, chose conservative A`
- åæ§é¡¹ä¸º WARN â éç¨ Card AI çæ¹æ¡ï¼æ 注 `# AI-REVIEW: disagreement/WARN, proceeded with B`
- åæ§é¡¹ä¸º SUGGEST â è®°å½ä½ä¸æ¹åæ¹æ¡
**å³çè®°å½**ï¼æ¯æ¬¡ AI-REVIEW 宿åï¼è¿½å å° `decisions.jsonl`ï¼è§å³ç审计追踪ï¼ã
### Level 3: AI-GATEï¼é»æ â å
³é®èç¹å¼ºå¶å®¡è®¡ï¼
éç¨ï¼Phase GateãCard 宿åçæç»éªè¯ãå·²å
ç½®äº autodev.sh ç Phase Gate æµç¨ä¸ã
**ä¸ Phase Gate çå
³ç³»**ï¼AI-GATE æ¯ Phase Gate çåéï¼ç± gate_check.sh + AI 审计ä¼è¯èªå¨æ§è¡ï¼æ é Card å
é¨è§¦åã
### å³ç审计追踪
æ¯æ¬¡ SPEC-DECISION æ AI-REVIEW 宿åï¼**å¿
é¡»**追å 䏿¡è®°å½ã
è·¯å¾æ¥æºï¼`build_prompt()` 伿³¨å
¥ `DECISIONS_FILE: /path/to/decisions.jsonl`ï¼Card AI ä»ä¸è·åè·¯å¾ã
```python
import json, datetime
# DECISIONS_FILE è·¯å¾ä» prompt ç"è¿è¡æ¶ä¿¡æ¯"é¨åè·å
decisions_path = "Autodev/{project_name}/decisions.jsonl" # 示ä¾
decision = {
"timestamp": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"card": "B.1", # å½å Card ID
"level": "AI-REVIEW", # SPEC-DECISION | AI-REVIEW
"reviewer_role": "Compatibility Reviewer", # AI-REVIEW å¡«å, SPEC-DECISION 为 null
"trigger": "backward compat impact",
"options": ["A: keyword-only", "B: positional"],
"chosen": "A",
"severity": "BLOCK", # BLOCK | WARN | SUGGEST
"consensus": True, # AI-REVIEW: 两个 AI æ¯å¦ä¸è´
"rationale": "preserves existing callers",
"residual_risk": "none",
"file": "src/engine.py",
"line": 42
}
with open(decisions_path, "a") as f:
f.write(json.dumps(decision, ensure_ascii=False) + "\n")
ç¨éï¼
- Gate 审计æ¶ç»è®¡å³çåå¸ï¼BLOCK/WARN/SUGGEST æ°éï¼
- æ£æµåºèµ° AI-REVIEW ä½åªèµ°äº SPEC-DECISION çéæ¼
build_prompt()èªå¨å°å·²æè®°å½æ³¨å ¥åç» Card ç promptï¼æä¾ååºå³çä¸ä¸æ
ç¦æ¢äºé¡¹
- â æ·»å è®¾è®¡ææ¡£æªæè¿°çåè½
- â è·³è¿æµè¯
- â ä¿®æ¹ Autodev/ ä¸çæä»¶ {PROJECT_SPECIFIC_PROHIBITIONS}
Skill 使ç¨è§å
â ï¸ å ¨èªå¨æµæ°´çº¿: æ¬ä¼è¯æ 人类å¨åºï¼éè¦äººç±»ç¡®è®¤çåºæ¯ç± AI äºå®¡æ¿ä»£ã
å¯ç¨ Skillï¼å·²éªè¯èªå¨åå®å ¨ï¼
| æ¶æº | Skill | 说æ |
|---|---|---|
| å¼å§å代ç å | /test-driven-development |
å¯å¨ TDD æµç¨ï¼å åæµè¯åå®ç° |
| æµè¯å¤±è´¥æ¶ | /systematic-debugging |
ç³»ç»åææ¥ï¼ç¦æ¢ç²çä¿®å¤ |
| Card 宿å | /verification-before-completion |
è¿è¡éªè¯å½ä»¤ç¡®è®¤å ¨é¨éè¿ |
| Card å« 2+ ç¬ç«æä»¶æ¶ | /dispatching-parallel-agents |
å¹¶è¡å¼åç¬ç«æ¨¡å |
åé人类确认ç Skill â AI äºå®¡æ¿ä»£
| å Skill | åé»å¡åå | æ¿ä»£æ¹æ¡ |
|---|---|---|
/brainstorming |
éç¨æ·éèæ¹å设计 | AI-REVIEW: spawn review agent å®¡æ ¸è®¾è®¡å³ç |
/subagent-driven-development |
å代çæé®é人类åç | AI-REVIEW: å³çç¹ç± review agent ç¡®è®¤ï¼æ§è¡ç¨ /dispatching-parallel-agents |
/requesting-code-review |
Critical issue éäººç±»å¤æ | AI-REVIEW: spawn review agent åç¬ç« code reviewï¼Phase Gate åæç»å®¡è®¡ |
Skill è°ç¨è§å
- TDD å¿
è°: æ¯å¼ Card å¼å§å®ç°æ¶ï¼å¿
é¡»å
è°ç¨
/test-driven-development - è°è¯å¿
è°: æµè¯å¤±è´¥ â¥1 次åï¼å¿
é¡»è°ç¨
/systematic-debugging - 宿å¿
è°: 声æ Card 宿åï¼å¿
é¡»è°ç¨
/verification-before-completion - å¹¶è¡ä¼å
: å½ Card å
å«å¤ä¸ªç¬ç«æä»¶æ¶ï¼ä¼å
ç¨
/dispatching-parallel-agents - å³çå级: ä½é£é©ç¨ SPEC-DECISION èªå³ï¼é«é£é©ç¨ AI-REVIEW äºå®¡
#### Card Template
```markdown
# Card {CARD_ID}: {CARD_TITLE}
## 读åè®¾è®¡ææ¡£
ä» `{SPEC_PATH}` 读åï¼
- {RELEVANT_SECTIONS}
ä» `{TODOLIST_PATH}` 读åï¼
- {RELEVANT_TASKS}
## 读åå·²æä»£ç
- {EXISTING_FILES_TO_READ}
## ä»»å¡
{TASKS_WITH_CODE_SNIPPETS}
## éªæ¶æ å
- [ ] AC-1: {ACCEPTANCE_CRITERION_1}
- [ ] AC-2: {ACCEPTANCE_CRITERION_2}
...
- [ ] AC-N: æææµè¯éè¿
- [ ] AC-N+1: ç°ææµè¯ä¸åå½±åï¼å¦éç¨ï¼
gate_check.sh Template
#!/bin/bash
set -e
PROJECT_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
AUTODEV_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$PROJECT_ROOT"
PASS=0; FAIL=0; WARN=0
check_pass() { echo -e "\033[0;32m â
$1\033[0m"; PASS=$((PASS+1)); }
check_fail() { echo -e "\033[0;31m â $1\033[0m"; FAIL=$((FAIL+1)); }
check_warn() { echo -e "\033[1;33m â ï¸ $1\033[0m"; WARN=$((WARN+1)); }
echo "âââââââââââââââââââââââââââââââââââââââââââââââ"
echo " {PROJECT_DISPLAY_NAME} â Phase Gate Checks"
echo "âââââââââââââââââââââââââââââââââââââââââââââââ"
# ââââ éç¨æ£æ¥ ââââ
# 1. æ ¸å¿åå
æµè¯
# 2. å
¨éå彿µè¯
# 3. SPEC-DECISION / AI-REVIEW 审计
echo ""
echo "ââ å³ç审计 ââ"
spec_count=$(grep -r "SPEC-DECISION" {SOURCE_DIRS} 2>/dev/null | wc -l | tr -d ' ')
review_count=$(grep -r "AI-REVIEW" {SOURCE_DIRS} 2>/dev/null | wc -l | tr -d ' ')
echo " SPEC-DECISION æ æ³¨: $spec_count å¤"
echo " AI-REVIEW æ æ³¨: $review_count å¤"
# 4. AI-REVIEW è¦ççæ£æ¥
# æ£æ¥è·¨æä»¶åæ´æ¯å¦æå¯¹åºç AI-REVIEW è®°å½
if [ -f "$AUTODEV_DIR/decisions.jsonl" ] && [ -s "$AUTODEV_DIR/decisions.jsonl" ]; then
block_count=$(grep -c '"severity": *"BLOCK"' "$AUTODEV_DIR/decisions.jsonl" 2>/dev/null || echo 0)
warn_count=$(grep -c '"severity": *"WARN"' "$AUTODEV_DIR/decisions.jsonl" 2>/dev/null || echo 0)
total_decisions=$(wc -l < "$AUTODEV_DIR/decisions.jsonl" | tr -d ' ')
review_decisions=$(grep -c '"level": *"AI-REVIEW"' "$AUTODEV_DIR/decisions.jsonl" 2>/dev/null || echo 0)
echo " decisions.jsonl: $total_decisions æ¡è®°å½ (AI-REVIEW: $review_decisions, BLOCK: $block_count, WARN: $warn_count)"
# æ£æ¥æ¯å¦ææªè§£å³ç BLOCK
unresolved_blocks=$(grep '"severity": *"BLOCK"' "$AUTODEV_DIR/decisions.jsonl" | grep '"consensus": *false' | wc -l | tr -d ' ')
if [ "$unresolved_blocks" -gt 0 ]; then
check_fail "åå¨ $unresolved_blocks 个æªè¾¾æå
±è¯ç BLOCK 级å³ç"
else
check_pass "ææ BLOCK 级å³ç已达æå
±è¯"
fi
else
check_warn "decisions.jsonl 为空æä¸åå¨ï¼æ æ³å®¡è®¡å³çè¦çç"
fi
# 5. è·¨æä»¶åæ´ vs AI-REVIEW å¹é
æ£æ¥ï¼Phase 级ï¼
phase_base_file="$AUTODEV_DIR/.phase_baseline"
phase_base_ref=""
[ -f "$phase_base_file" ] && phase_base_ref=$(cat "$phase_base_file")
if [ -n "$phase_base_ref" ] && git rev-parse --verify "${phase_base_ref}^{commit}" >/dev/null 2>&1; then
changed_files=$(git diff --name-only "$phase_base_ref" -- 2>/dev/null | wc -l | tr -d ' ')
echo " Phase åºçº¿: $phase_base_ref"
phase_review_count=0
while IFS= read -r changed_file; do
[ -f "$changed_file" ] || continue
file_review_count=$(grep -c "AI-REVIEW" "$changed_file" 2>/dev/null || true)
phase_review_count=$((phase_review_count + file_review_count))
done < <(git diff --name-only "$phase_base_ref" -- 2>/dev/null)
else
changed_files=$(git diff --name-only HEAD 2>/dev/null | wc -l | tr -d ' ')
phase_review_count=$review_count
check_warn "æªæ¾å°ææ .phase_baselineï¼æåéå°å·¥ä½åº diffï¼å»ºè®®æ¯ä¸ª Gate æååæ´æ°è¯¥åºçº¿"
fi
if [ "$changed_files" -gt 3 ] && [ "$phase_review_count" -eq 0 ]; then
check_warn "æ¬ Phase åæ´äº $changed_files 个æä»¶ä½ä»£ç 䏿 AI-REVIEW æ æ³¨"
else
check_pass "AI-REVIEW è¦ççæ£å¸¸ ($changed_files æä»¶åæ´, æ¬ Phase $phase_review_count å¤ AI-REVIEW æ æ³¨)"
fi
# ââââ 项ç®ç¹å®æ£æ¥ (å®å¶) ââââ
# 6-N. {PROJECT_SPECIFIC_CHECKS}
# ââââ æ±æ» ââââ
echo ""
echo "âââââââââââââââââââââââââââââââââââââââââââââââ"
echo "ç»æ: â
$PASS | â $FAIL | â ï¸ $WARN"
[ $FAIL -gt 0 ] && exit 1 || exit 0
phase_gate.md Template
# Phase Gate 审计
## ä½ çè§è²
ä½ æ¯ {PROJECT_NAME} çåè§å®¡è®¡åã
## 审计æ¥éª¤
1. 读åè®¾è®¡ææ¡£
2. 读å代ç åæ´ï¼git diffï¼
3. éé¡¹æ£æ¥ï¼é¡¹ç®ç¹å®æ£æ¥æ¸
åï¼
4. è¿è¡æµè¯
5. **å³ç审计**ï¼è¯»å `{AUTODEV_DIR}/decisions.jsonl`ï¼æ£æ¥ï¼
- ææ BLOCK 级å³çæ¯å¦å·²è¾¾æå
±è¯
- è·¨æä»¶åæ´æ¯å¦æå¯¹åº AI-REVIEW è®°å½
- SPEC-DECISION çæ®ä½é£é©æ¯å¦åç
- ç»è®¡æ¬ Phase å³çåå¸ï¼SPEC-DECISION vs AI-REVIEW, BLOCK/WARN/SUGGESTï¼
6. è¾åºå®¡è®¡æ¥åï¼éè¿é¡¹ / P0-P2 é®é¢ / å³ç审计æè¦ / ç»è®ºï¼
Step 5: Verify
After generating all files:
chmod +x autodev.sh gate_check.sh- Run
./autodev.sh --dry-runâ verify all steps listed correctly - Run
./autodev.sh --statusâ verify display works - Run
./autodev.sh --helpâ verify help text - Verify all card files exist:
ls cards/ - Verify state file is empty:
cat state - Verify decisions.jsonl exists and is empty:
test -f decisions.jsonl && [ ! -s decisions.jsonl ] - Verify summary.md does NOT exist yet (it’s auto-generated at runtime)
- Verify generated files contain no unresolved placeholders/stubs:
! rg -n '\{(PROJECT|SPEC|TODOLIST|TEST_CMD|ALL_STEPS_CONTENT|FIRST_CARD_ID|SOURCE_DIRS|AUTODEV_PATH|ENV_PREFIX|ADDITIONAL_FILES|RELEVANT|EXISTING_FILES|ACCEPTANCE_CRITERION|CARD_TITLE|REVIEWER_ROLE|TASKS_WITH)[^}]*\}' autodev.sh gate_check.sh system_prompt.md cards/*.md! rg -n 'show_help\(\) \{ \.\.\. \}|show_status\(\) \{ \.\.\. \}' autodev.sh
Key Principles
- Todolist is the source of truth â every Card traces back to todolist tasks
- P1/P2 fixes become constraints â embed audit corrections into Card acceptance criteria
- Test command is sacred â must match what the todolist specifies
- Backward compatibility â if todolist mentions fallback/compatibility, enforce in gate checks
- No gold-plating â Cards only implement what the todolist describes
- Each Card is self-contained â reads its own context, doesn’t assume prior Card output was read
Generator Self-Check
After generating all files, verify these cross-cutting concerns:
- system_prompt.md contains the full 3-level decision protocol (copy from template verbatim)
- Reviewer role table is customized for the project (add/remove roles as needed; severity levels BLOCK/WARN/SUGGEST are universal â never modify)
- gate_check.sh includes decisions.jsonl audit checks
- phase_gate.md includes decision audit as step 5
- All fix prompts include: test output verbatim, spec/todolist references, “no extra changes”, backward compatibility reminder
decisions.jsonlpath flows correctly: config var âbuild_prompt()injectsDECISIONS_FILE:â Card AI reads it from prompt