worker-dispatch
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWorker Dispatch
Worker调度
Overview
概述
Spawns and manages worker Codex processes in isolated git worktrees. Workers are disposable - if they fail, spawn another.
Core principle: Workers are isolated, scoped, and expendable. State lives in GitHub, not in workers.
Announce at start: "I'm using worker-dispatch to spawn a worker for issue #[N]."
在独立的Git工作树中生成并管理Worker Codex进程。Worker是可丢弃的——如果它们运行失败,就重新生成一个。
核心原则:Worker是独立的、有作用域的且可消耗的。状态存储在GitHub中,而非Worker内部。
启动时声明:"我正在使用worker-dispatch为#[N]号任务生成一个Worker。"
State Management
状态管理
CRITICAL: Worker state is stored in GitHub. NO local state files for tracking.
| State | Location | Purpose |
|---|---|---|
| Worker assignment | Issue comment | Who is working on what |
| Worker status | Project Board | In Progress, Done, etc. |
| Process logs | Local (ephemeral) | Debugging only |
| Process PIDs | Local (ephemeral) | Process management only |
Local files (logs, PIDs) are ephemeral - they exist only for the current orchestration session. All persistent state is in GitHub.
关键注意事项:Worker状态存储在GitHub中,不使用本地状态文件进行追踪。
| 状态 | 存储位置 | 用途 |
|---|---|---|
| Worker分配信息 | 任务评论区 | 记录谁在处理什么任务 |
| Worker状态 | 项目看板 | 标记进行中、已完成等状态 |
| 进程日志 | 本地(临时) | 仅用于调试 |
| 进程PID | 本地(临时) | 仅用于进程管理 |
本地文件(日志、PID)是临时的——仅在当前编排会话期间存在。所有持久化状态均存储在GitHub中。
Worker Architecture
Worker架构
Main Repository (./)
│
└── Worktrees (parallel directories)
│
├── ../project-worker-123/ ← Worker for issue #123
│ └── (full repo copy on feature/123-* branch)
│
├── ../project-worker-124/ ← Worker for issue #124
│ └── (full repo copy on feature/124-* branch)
│
└── ../project-worker-125/ ← Worker for issue #125
└── (full repo copy on feature/125-* branch)主仓库 (./)
│
└── 工作树(并行目录)
│
├── ../project-worker-123/ ← 用于#123号任务的Worker
│ └── (feature/123-*分支上的完整仓库副本)
│
├── ../project-worker-124/ ← 用于#124号任务的Worker
│ └── (feature/124-*分支上的完整仓库副本)
│
└── ../project-worker-125/ ← 用于#125号任务的Worker
└── (feature/125-*分支上的完整仓库副本)Spawning a Worker
生成Worker
Step 1: Create Worktree
步骤1:创建工作树
bash
spawn_worker() {
issue=$1
context_file=$2 # Optional: handover context
worker_id="worker-$(date +%s)-$issue"
issue_title=$(gh issue view "$issue" --json title --jq '.title' | \
tr '[:upper:]' '[:lower:]' | \
sed 's/[^a-z0-9]/-/g' | \
cut -c1-40)
branch="feature/$issue-$issue_title"
worktree_path="../$(basename $PWD)-worker-$issue"
git fetch origin main
git branch "$branch" origin/main 2>/dev/null || true
git worktree add "$worktree_path" "$branch"
echo "Created worktree: $worktree_path on branch $branch"
}bash
spawn_worker() {
issue=$1
context_file=$2 # 可选:移交上下文
worker_id="worker-$(date +%s)-$issue"
issue_title=$(gh issue view "$issue" --json title --jq '.title' | \
tr '[:upper:]' '[:lower:]' | \
sed 's/[^a-z0-9]/-/g' | \
cut -c1-40)
branch="feature/$issue-$issue_title"
worktree_path="../$(basename $PWD)-worker-$issue"
git fetch origin main
git branch "$branch" origin/main 2>/dev/null || true
git worktree add "$worktree_path" "$branch"
echo "Created worktree: $worktree_path on branch $branch"
}Step 2: Register Worker in GitHub
步骤2:在GitHub中注册Worker
Post worker assignment to the issue as a structured comment:
bash
register_worker() {
worker_id=$1
issue=$2
worktree=$3
# Post assignment comment with structured marker
gh issue comment "$issue" --body "<!-- WORKER:ASSIGNED -->
\`\`\`json
{
\"assigned\": true,
\"worker_id\": \"$worker_id\",
\"assigned_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
\"worktree\": \"$worktree\"
}
\`\`\`
<!-- /WORKER:ASSIGNED -->
**Worker Assigned**
- **Worker ID:** \`$worker_id\`
- **Started:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
- **Worktree:** \`$worktree\`
---
*Orchestrator: $ORCHESTRATION_ID*"
# Update project board status
update_project_status "$issue" "In Progress"
}将Worker分配信息以结构化评论的形式发布到任务中:
bash
register_worker() {
worker_id=$1
issue=$2
worktree=$3
# 发布带结构化标记的分配评论
gh issue comment "$issue" --body "<!-- WORKER:ASSIGNED -->
\`\`\`json
{
\"assigned\": true,
\"worker_id\": \"$worker_id\",
\"assigned_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
\"worktree\": \"$worktree\"
}
\`\`\`
<!-- /WORKER:ASSIGNED -->
**Worker已分配**
- **Worker ID:** \`$worker_id\`
- **启动时间:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
- **工作树:** \`$worktree\`
---
*编排器:$ORCHESTRATION_ID*"
# 更新项目看板状态
update_project_status "$issue" "进行中"
}Step 3: Construct Worker Prompt
步骤3:构建Worker提示词
bash
construct_worker_prompt() {
issue=$1
worker_id=$2
context_file=$3
attempt=$4
research_context=$5
cat <<PROMPT
You are a worker agent. Your ONLY task is to complete GitHub issue #$issue.bash
construct_worker_prompt() {
issue=$1
worker_id=$2
context_file=$3
attempt=$4
research_context=$5
cat <<PROMPT
You are a worker agent. Your ONLY task is to complete GitHub issue #$issue.Worker Identity
Worker Identity
- Worker ID: $worker_id
- Issue: #$issue
- Attempt: $attempt
- Orchestration: $ORCHESTRATION_ID
- Worker ID: $worker_id
- Issue: #$issue
- Attempt: $attempt
- Orchestration: $ORCHESTRATION_ID
Your Mission
Your Mission
Complete issue #$issue by following the issue-driven-development workflow:
- Read and understand the issue completely
- Create/verify you're on the correct branch
- Implement the solution with TDD
- Run all tests
- Create a PR when complete
- Update issue with progress comments throughout
Complete issue #$issue by following the issue-driven-development workflow:
- Read and understand the issue completely
- Create/verify you're on the correct branch
- Implement the solution with TDD
- Run all tests
- Create a PR when complete
- Update issue with progress comments throughout
Constraints
Constraints
- Work ONLY on issue #$issue - no other issues
- Do NOT modify unrelated code
- Do NOT start other work
- Follow all project skills (strict-typing, ipv6-first, etc.)
- Maximum 100 turns - if approaching limit, prepare handover
- Work ONLY on issue #$issue - no other issues
- Do NOT modify unrelated code
- Do NOT start other work
- Follow all project skills (strict-typing, ipv6-first, etc.)
- Maximum 100 turns - if approaching limit, prepare handover
Exit Conditions
Exit Conditions
Exit when ANY of these occur:
- PR Created - Your work is complete
- Blocked - You cannot proceed without external input
- Turns Exhausted - Approaching 100 turns, handover needed
- Failed - Tests fail after good-faith effort (triggers research)
Exit when ANY of these occur:
- PR Created - Your work is complete
- Blocked - You cannot proceed without external input
- Turns Exhausted - Approaching 100 turns, handover needed
- Failed - Tests fail after good-faith effort (triggers research)
Progress Reporting
Progress Reporting
Update the issue with comments as you work.
Update the issue with comments as you work.
On Completion
On Completion
Post completion comment to the issue.
Post completion comment to the issue.
On Handover Needed
On Handover Needed
Post handover context to the issue comment (NOT local file).
$(if [ -n "$context_file" ] && [ -f "$context_file" ]; then
echo "## Context from Previous Worker"
cat "$context_file"
fi)
$(if [ -n "$research_context" ]; then
echo "## Research Context (Previous Failures)"
echo "$research_context"
fi)
Post handover context to the issue comment (NOT local file).
$(if [ -n "$context_file" ] && [ -f "$context_file" ]; then
echo "## Context from Previous Worker"
cat "$context_file"
fi)
$(if [ -n "$research_context" ]; then
echo "## Research Context (Previous Failures)"
echo "$research_context"
fi)
Begin
Begin
Start by reading issue #$issue to understand the requirements.
PROMPT
}
undefinedStart by reading issue #$issue to understand the requirements.
PROMPT
}
undefinedStep 4: Spawn Process
步骤4:生成进程
bash
spawn_worker_process() {
issue=$1
worker_id=$2
worktree_path=$3
prompt=$4
# Create local ephemeral directories
mkdir -p ".codex/logs" ".codex/pids"
log_file=".codex/logs/$worker_id.log"
pid_file=".codex/pids/$worker_id.pid"
(
cd "$worktree_path"
codex exec --dangerously-bypass-approvals-and-sandbox --json -C "$worktree_path" "$prompt" 2>&1
) > "$log_file" &
worker_pid=$!
echo "$worker_pid" > "$pid_file"
echo "Spawned worker $worker_id (PID: $worker_pid) for issue #$issue"
}bash
spawn_worker_process() {
issue=$1
worker_id=$2
worktree_path=$3
prompt=$4
# 创建本地临时目录
mkdir -p ".codex/logs" ".codex/pids"
log_file=".codex/logs/$worker_id.log"
pid_file=".codex/pids/$worker_id.pid"
(
cd "$worktree_path"
codex exec --dangerously-bypass-approvals-and-sandbox --json -C "$worktree_path" "$prompt" 2>&1
) > "$log_file" &
worker_pid=$!
echo "$worker_pid" > "$pid_file"
echo "Spawned worker $worker_id (PID: $worker_pid) for issue #$issue"
}Complete Spawn Function
完整的生成函数
bash
spawn_worker() {
issue=$1
context_file=${2:-""}
attempt=${3:-1}
research_context=${4:-""}
worker_id="worker-$(date +%s)-$issue"
worktree_path=$(create_worktree "$issue" "$worker_id")
prompt=$(construct_worker_prompt "$issue" "$worker_id" "$context_file" "$attempt" "$research_context")
# Register in GitHub BEFORE spawning
register_worker "$worker_id" "$issue" "$worktree_path"
# Spawn process
spawn_worker_process "$issue" "$worker_id" "$worktree_path" "$prompt"
log_activity "worker_spawned" "$worker_id" "$issue"
}bash
spawn_worker() {
issue=$1
context_file=${2:-""}
attempt=${3:-1}
research_context=${4:-""}
worker_id="worker-$(date +%s)-$issue"
worktree_path=$(create_worktree "$issue" "$worker_id")
prompt=$(construct_worker_prompt "$issue" "$worker_id" "$context_file" "$attempt" "$research_context")
# 生成进程前先在GitHub注册
register_worker "$worker_id" "$issue" "$worktree_path"
# 生成进程
spawn_worker_process "$issue" "$worker_id" "$worktree_path" "$prompt"
log_activity "worker_spawned" "$worker_id" "$issue"
}Tool Scoping
工具范围
Standard Worker (Full Implementation)
标准Worker(完整实现)
bash
--allowedTools "Bash,Read,Edit,Write,Grep,Glob,mcp__git__*,mcp__github__*,mcp__memory__*,WebFetch,WebSearch"bash
--allowedTools "Bash,Read,Edit,Write,Grep,Glob,mcp__git__*,mcp__github__*,mcp__memory__*,WebFetch,WebSearch"Research Worker (Read-Only)
研究型Worker(只读)
bash
--allowedTools "Read,Grep,Glob,WebFetch,WebSearch,mcp__memory__*,mcp__github__get_issue,mcp__github__get_pull_request"bash
--allowedTools "Read,Grep,Glob,WebFetch,WebSearch,mcp__memory__*,mcp__github__get_issue,mcp__github__get_pull_request"Review Worker (No Edits)
评审型Worker(禁止编辑)
bash
--allowedTools "Read,Grep,Glob,Bash(pnpm test:*),Bash(pnpm lint:*)"bash
--allowedTools "Read,Grep,Glob,Bash(pnpm test:*),Bash(pnpm lint:*)"Checking Worker Status
检查Worker状态
Check both GitHub and local PID:
bash
check_worker_status() {
worker_id=$1
issue=$2
pid_file=".codex/pids/$worker_id.pid"
if [ ! -f "$pid_file" ]; then
echo "unknown"
return
fi
pid=$(cat "$pid_file")
if ! kill -0 "$pid" 2>/dev/null; then
# Process exited - check GitHub for status
pr_exists=$(gh pr list --head "feature/$issue-*" --json number --jq 'length')
if [ "$pr_exists" -gt 0 ]; then
echo "completed"
else
# Check issue comments for status
log_file=".codex/logs/$worker_id.log"
if [ -f "$log_file" ]; then
if grep -q 'handover' "$log_file"; then
echo "handover_needed"
elif grep -q 'blocked' "$log_file"; then
echo "blocked"
else
echo "failed"
fi
else
echo "unknown"
fi
fi
else
echo "running"
fi
}同时检查GitHub和本地PID:
bash
check_worker_status() {
worker_id=$1
issue=$2
pid_file=".codex/pids/$worker_id.pid"
if [ ! -f "$pid_file" ]; then
echo "unknown"
return
fi
pid=$(cat "$pid_file")
if ! kill -0 "$pid" 2>/dev/null; then
# 进程已退出 - 检查GitHub状态
pr_exists=$(gh pr list --head "feature/$issue-*" --json number --jq 'length')
if [ "$pr_exists" -gt 0 ]; then
echo "completed"
else
# 检查任务评论获取状态
log_file=".codex/logs/$worker_id.log"
if [ -f "$log_file" ]; then
if grep -q 'handover' "$log_file"; then
echo "handover_needed"
elif grep -q 'blocked' "$log_file"; then
echo "blocked"
else
echo "failed"
fi
else
echo "unknown"
fi
fi
else
echo "running"
fi
}Worker Cleanup
Worker清理
bash
cleanup_worker() {
worker_id=$1
issue=$2
keep_worktree=${3:-false}
worktree="../$(basename $PWD)-worker-$issue"
# Remove worktree (unless keeping for inspection)
if [ "$keep_worktree" = "false" ] && [ -d "$worktree" ]; then
git worktree remove "$worktree" --force 2>/dev/null || true
git worktree prune
fi
# Clean up local ephemeral files
rm -f ".codex/pids/$worker_id.pid"
# Post cleanup comment to issue
gh issue comment "$issue" --body "<!-- WORKER:ASSIGNED -->
\`\`\`json
{\"assigned\": false, \"cleared_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}
\`\`\`
<!-- /WORKER:ASSIGNED -->
**Worker Cleaned Up**
- **Worker ID:** \`$worker_id\`
- **Cleared:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
---
*Orchestrator: $ORCHESTRATION_ID*"
log_activity "worker_cleaned" "$worker_id" "$issue"
}bash
cleanup_worker() {
worker_id=$1
issue=$2
keep_worktree=${3:-false}
worktree="../$(basename $PWD)-worker-$issue"
# 移除工作树(除非需要保留用于检查)
if [ "$keep_worktree" = "false" ] && [ -d "$worktree" ]; then
git worktree remove "$worktree" --force 2>/dev/null || true
git worktree prune
fi
# 清理本地临时文件
rm -f ".codex/pids/$worker_id.pid"
# 在任务中发布清理完成的评论
gh issue comment "$issue" --body "<!-- WORKER:ASSIGNED -->
\`\`\`json
{\"assigned\": false, \"cleared_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}
\`\`\`
<!-- /WORKER:ASSIGNED -->
**Worker已清理**
- **Worker ID:** \`$worker_id\`
- **清理时间:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
---
*编排器:$ORCHESTRATION_ID*"
log_activity "worker_cleaned" "$worker_id" "$issue"
}Replacement Worker (After Handover)
替换Worker(移交后)
bash
spawn_replacement_worker() {
old_worker_id=$1
issue=$2
worktree=$3
# Get handover context from issue comments
handover_context=$(gh api "/repos/$OWNER/$REPO/issues/$issue/comments" \
--jq '[.[] | select(.body | contains("<!-- HANDOVER:START -->"))] | last | .body' 2>/dev/null || echo "")
# Cleanup old worker but KEEP worktree
cleanup_worker "$old_worker_id" "$issue" true
# Spawn replacement with handover context
new_worker_id="worker-$(date +%s)-$issue"
attempt=$(($(get_attempt_count "$issue") + 1))
prompt=$(construct_worker_prompt "$issue" "$new_worker_id" "" "$attempt" "$handover_context")
register_worker "$new_worker_id" "$issue" "$worktree"
spawn_worker_process "$issue" "$new_worker_id" "$worktree" "$prompt"
log_activity "worker_replacement" "$new_worker_id" "$issue" "$old_worker_id"
}bash
spawn_replacement_worker() {
old_worker_id=$1
issue=$2
worktree=$3
# 从任务评论中获取移交上下文
handover_context=$(gh api "/repos/$OWNER/$REPO/issues/$issue/comments" \
--jq '[.[] | select(.body | contains("<!-- HANDOVER:START -->"))] | last | .body' 2>/dev/null || echo "")
# 清理旧Worker但保留工作树
cleanup_worker "$old_worker_id" "$issue" true
# 使用移交上下文生成新Worker
new_worker_id="worker-$(date +%s)-$issue"
attempt=$(($(get_attempt_count "$issue") + 1))
prompt=$(construct_worker_prompt "$issue" "$new_worker_id" "" "$attempt" "$handover_context")
register_worker "$new_worker_id" "$issue" "$worktree"
spawn_worker_process "$issue" "$new_worker_id" "$worktree" "$prompt"
log_activity "worker_replacement" "$new_worker_id" "$issue" "$old_worker_id"
}Parallel Dispatch
并行调度
bash
dispatch_available_slots() {
max_workers=5
# Count current workers from project board (In Progress status)
current=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \
--format json | jq '[.items[] | select(.status.name == "In Progress")] | length')
available=$((max_workers - current))
if [ "$available" -le 0 ]; then
echo "No worker slots available ($current/$max_workers active)"
return
fi
echo "Dispatching up to $available workers..."
for i in $(seq 1 $available); do
next_issue=$(get_next_pending_issue)
if [ -z "$next_issue" ]; then
echo "No more pending issues"
break
fi
spawn_worker "$next_issue"
done
}bash
dispatch_available_slots() {
max_workers=5
# 统计项目看板中当前的Worker数量(状态为进行中)
current=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \
--format json | jq '[.items[] | select(.status.name == "In Progress")] | length')
available=$((max_workers - current))
if [ "$available" -le 0 ]; then
echo "No worker slots available ($current/$max_workers active)"
return
fi
echo "Dispatching up to $available workers..."
for i in $(seq 1 $available); do
next_issue=$(get_next_pending_issue)
if [ -z "$next_issue" ]; then
echo "No more pending issues"
break
fi
spawn_worker "$next_issue"
done
}Checklist
检查清单
When spawning a worker:
- Worktree created successfully
- Branch created/checked out
- Worker registered in GitHub (issue comment)
- Project board status updated to In Progress
- Worker prompt constructed with all context
- Appropriate tool scoping applied
- Process spawned in background
- Activity logged
When cleaning up:
- Worker process terminated (or already exited)
- Worktree removed (unless keeping for inspection)
- Cleanup comment posted to issue
- Activity logged
生成Worker时:
- 工作树创建成功
- 分支已创建/检出
- Worker已在GitHub注册(任务评论)
- 项目看板状态已更新为“进行中”
- Worker提示词已包含所有上下文信息
- 已应用合适的工具范围
- 进程已在后台生成
- 活动已记录
清理Worker时:
- Worker进程已终止(或已自行退出)
- 工作树已移除(除非保留用于检查)
- 任务中已发布清理完成的评论
- 活动已记录
Integration
集成
This skill is used by:
- - Main orchestration loop
autonomous-orchestration
This skill uses:
- - Behavior injected into prompts
worker-protocol - - Handover context format
worker-handover
本技能被以下工具使用:
- - 主编排循环
autonomous-orchestration
本技能依赖以下工具:
- - 注入到提示词中的行为规范
worker-protocol - - 移交上下文格式
worker-handover