关于 flow-parallel
flow-parallel 是面向 Codex CLI 的技能,可将复合任务拆成独立工作包,并通过独立 Claude 进程执行。它生成工作分解、验证依赖关系、分波启动工作进程并汇总结果。
主要功能
- 01生成工作分解结构
- 02验证依赖并分配执行波次
- 03生成工作包指令与启动文件
- 04通过 Git worktree 隔离工作
- 05监控工作进程并汇总结果
适用场景
- 01将复合任务拆分为并行工作
- 02按执行波次运行有依赖的工作包
- 03检查并行工作进程的输出与警告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nyldn/ claude-octopus --skill flow-parallel安装后在 Claude Code 中输入/flow-parallel确认已加载。
附带文件agents/openai.yaml
详细介绍
主机:Codex CLI — 此技能专为 Claude Code 设计,并已适配 Codex。 交叉引用命令在 Codex 中使用已安装的技能名称,而不是
/octo:*斜杠命令。 使用当前 Codex shell 和子 Agent 工具。在当前会话尚未提供之前,不要声称某个提供商、模型或主机子 Agent 可用。 有关主机工具的对应项,请参阅skills/blocks/codex-host-adapter.md。
停止 — 技能已加载
不要再次调用 Skill()。不要加载任何其他技能。直接执行。
执行约定(强制 — 不可跳过)
此技能使用强制执行模式。你必须严格按照以下 7 个步骤执行。
架构原则: 主机子 Agent 工具子 Agent 不会加载插件。独立的 claude -p 进程会加载插件。此技能会启动独立的 claude -p 进程,因此每个工作包都能获得完整的 Octopus 插件、独立的 Double Diamond、Agent 和质量关卡。
步骤 1:澄清问题(强制)
在执行任何其他操作之前,必须通过 AskUserQuestion 提问。
你必须向用户收集以下信息——如果没有任务范围、数量和依赖关系的答案,拆分结果会很笼统,并产生相互重叠的工作包,导致合并冲突:
AskUserQuestion with these questions:
1. **Compound task**: What compound task should be decomposed?
- Use inline args if provided (e.g., /octo:parallel "build auth system")
- If no args: ask "What compound task should I decompose into parallel work packages?"
2. **Work package count**: How many work packages?
- Options: "3 (Recommended)", "4", "5", "Custom (up to 10)"
- Default: 3-5 is optimal
3. **Dependencies**: Are the work packages independent?
- "Fully independent - no dependencies between packages (Recommended)"
- "Some dependencies - packages may need to share interfaces"
- "Sequential dependencies - packages must complete in order"
如果用户在命令中直接提供了描述(例如 /octo:parallel build a full auth system with OAuth, RBAC, and audit logging),请将其作为任务描述,但仍须询问剩余问题(数量、依赖关系)。
如果用户对任何问题回答“跳过”,则使用默认值:3 个工作包,彼此完全独立。
在问题得到回答之前,不要继续执行步骤 2。
步骤 2:显示可视化指示信息(强制 — 阻塞)
强制要求:必须先使用原生 shell 命令工具运行提供商检查,然后再显示横幅。不要跳过。不要假定提供商可用。
bash "${HOME}/.claude-octopus/plugin/scripts/helpers/check-providers.sh"
使用下方的实际结果。禁止只显示“🔵 Claude:可用 ✓”而不列出所有提供商。
在任何任务拆分之前,根据实际状态显示此横幅:
🐙 CLAUDE OCTOPUS ACTIVATED - Team of Teams Mode
Parallel Phase: Decomposing compound task into N independent work packages
Architecture:
Main (this session) - Orchestrator: decompose, launch, monitor, aggregate
WP-1..WP-N (claude -p) - Independent workers with full plugin capabilities
Each worker:
- Runs as independent claude -p process in its own git worktree
- Loads full Octopus plugin
- Has own context, tools, and quality gates
- Produces output.md + exit-code
- Tracked in agent registry (~/.claude-octopus/agents/registry.json)
Estimated Time: 5-15 minutes (depending on task complexity)
在显示横幅之前,不要继续执行步骤 3。
步骤 3:读取先前状态(强制 — 状态管理)
拆分任务之前,读取任何先前上下文:
# Initialize state if needed
if [[ -d ".octo" ]]; then
echo "Found existing .octo/ state directory"
else
echo "No prior .octo/ state found - starting fresh"
fi
# Check for prior discover/spec context
if [[ -f ".octo/STATE.md" ]]; then
echo "Prior state found:"
cat .octo/STATE.md
fi
if [[ -f ".octo/PROJECT.md" ]]; then
echo "Prior project context found:"
cat .octo/PROJECT.md
fi
使用任何先前上下文(发现结果、规范定义、项目状态)来指导 WBS 拆分。
在读取状态之前,不要继续执行步骤 4。
步骤 4:拆分为 WBS(强制)
Claude 会分析复合任务并生成工作分解结构。
拆分规则:
- 拆分为 3–5 个独立工作包(WP-1 至 WP-N,最多 10 个)
- 每个工作包都须包含:名称、范围说明、预期输出文件、依赖关系
- 验证:范围互不重叠,且合起来涵盖全部任务
- 每个工作包都必须足够独立,可由一个独立的
claude -p进程处理
创建协调目录和 WBS:
# Create parallel coordination directory
mkdir -p .octo/parallel
# Write wbs.json
cat > .octo/parallel/wbs.json << 'WBSEOF'
{
"task": "<compound task description>",
"created": "<ISO timestamp>",
"work_packages": [
{
"id": "WP-1",
"name": "<work package name>",
"scope": "<what this WP covers>",
"expected_outputs": ["<list of files this WP should produce>"],
"dependencies": [],
"wave": 1,
"branch": "<a branch name unique to this work package>",
"status": "pending"
}
]
}
WBSEOF
必须根据你对复合任务的分析编写实际的 WBS 内容。 上方的 JSON 只是模板——请填入真实的任务拆分。模板或占位符 WBS 会产生含糊的指令,导致各 Agent 对指令的理解不同,进而造成重复劳动或遗漏任务范围。
验证关卡:wbs_generated — 验证 .octo/parallel/wbs.json 存在且包含有效 JSON:
# Validate WBS was created
if [[ -f ".octo/parallel/wbs.json" ]]; then
python3 -c "import json; json.load(open('.octo/parallel/wbs.json')); print('WBS validation: PASSED')" 2>/dev/null || echo "WBS validation: FAILED - invalid JSON"
else
echo "WBS validation: FAILED - file not found"
fi
在 WBS 验证通过之前,不要继续执行步骤 5。
第 4.5 步:对抗式 WBS 交叉核查(推荐)
生成 WBS 后、验证依赖项之前,使用第二个模型交叉核查任务分解。 单模型分解常会产生隐藏依赖、接口契约不明确或范围缺漏,导致合并冲突和重复工作。
如果有外部提供商可用,请通过 Octopus 路由发送 WBS 进行对抗式审查:
WBS_CONTENT=$(<".octo/parallel/wbs.json")
review_provider=""
command -v codex >/dev/null 2>&1 && review_provider="codex"
[[ -z "$review_provider" ]] && command -v agy >/dev/null 2>&1 && review_provider="agy"
if [[ -n "$review_provider" ]]; then
"${HOME}/.claude-octopus/plugin/scripts/orchestrate.sh" spawn "$review_provider" \
"Review this Work Breakdown Structure for a parallel execution pipeline. Your job is to find problems BEFORE agents start working.
1. What DEPENDENCIES between work packages were missed? (e.g., WP-2 needs a type definition from WP-1 but doesn't declare it)
2. What INTERFACE CONTRACTS are ambiguous? (e.g., two WPs will create conflicting exports, or expect different API signatures)
3. Do any work packages OVERLAP in scope? (e.g., both WP-1 and WP-3 might modify the same file)
4. Are there GAPS — things no work package covers?
WBS:
${WBS_CONTENT}" 2>/dev/null || true
fi
收到质疑后:
- 如果发现范围重叠:调整 WBS 中的 WP 边界和文件路径
- 如果发现缺失依赖项:将其添加到
dependencies数组中 - 如果发现接口含糊不清:在受影响 WP 的说明中添加明确的集成契约部分
- 如果发现缺漏:要么添加新的 WP,要么扩展现有 WP 的范围
使用 --fast 跳过,或在用户明确要求优先速度而非全面性时跳过。
第 4.6 步:依赖验证与波次分配(必须)
如果任何工作包的 dependencies 非空,请验证依赖图并分配波次编号。
如果所有工作包的 "dependencies": [],则跳过此步骤——它们的波次均为 1(向后兼容)。
运行依赖验证和波次分配:
python3 << 'DEPEOF'
import json, sys
with open('.octo/parallel/wbs.json') as f:
wbs = json.load(f)
packages = wbs['work_packages']
ids = {wp['id'] for wp in packages}
deps = {wp['id']: wp.get('dependencies', []) for wp in packages}
# Check for missing references
errors = []
for wp_id, wp_deps in deps.items():
for dep in wp_deps:
if dep not in ids:
errors.append(f"WP {wp_id} depends on unknown {dep}")
if errors:
print("DEPENDENCY VALIDATION: FAILED")
for e in errors:
print(f" ERROR: {e}")
sys.exit(1)
# Cycle detection (DFS)
WHITE, GRAY, BLACK = 0, 1, 2
color = {wp_id: WHITE for wp_id in ids}
def has_cycle(node, path):
color[node] = GRAY
for dep in deps[node]:
if color[dep] == GRAY:
cycle = path[path.index(dep):] + [dep]
return cycle
if color[dep] == WHITE:
result = has_cycle(dep, path + [dep])
if result:
return result
color[node] = BLACK
return None
for wp_id in ids:
if color[wp_id] == WHITE:
cycle = has_cycle(wp_id, [wp_id])
if cycle:
print(f"DEPENDENCY VALIDATION: FAILED - Cycle detected: {' -> '.join(cycle)}")
sys.exit(1)
# Topological sort and wave assignment
waves = {}
assigned = set()
def get_wave(wp_id):
if wp_id in waves:
return waves[wp_id]
if not deps[wp_id]:
waves[wp_id] = 1
return 1
max_dep_wave = max(get_wave(d) for d in deps[wp_id])
waves[wp_id] = max_dep_wave + 1
return waves[wp_id]
for wp_id in ids:
get_wave(wp_id)
# Update WBS with wave assignments
for wp in packages:
wp['wave'] = waves[wp['id']]
with open('.octo/parallel/wbs.json', 'w') as f:
json.dump(wbs, f, indent=2)
max_wave = max(waves.values())
print(f"DEPENDENCY VALIDATION: PASSED")
print(f"Waves assigned: {max_wave}")
for w in range(1, max_wave + 1):
wave_wps = [wp_id for wp_id, wave in waves.items() if wave == w]
print(f" Wave {w}: {', '.join(wave_wps)}")
DEPEOF
如果验证失败: 向用户报告错误并停止。不要继续执行无效依赖项。
在依赖项验证通过之前(或跳过此步骤,因为 WP 彼此独立),不要继续执行第 5 步。
第 5 步:生成说明文件(必须)
为 WBS 中的每个工作包创建一个说明文件和一个启动脚本。
对于每个 WP-N,创建:
instructions.md
mkdir -p ".octo/parallel/WP-N"
cat > ".octo/parallel/WP-N/instructions.md" << 'INSTREOF'
# Work Package WP-N: <name>
## Task
<Clear description of what this work package must accomplish>
## Scope Boundaries
- IN SCOPE: <what this WP covers>
- OUT OF SCOPE: <what other WPs handle — explicit boundaries>
## Expected Output
- Files to create/modify: <explicit file paths — MANDATORY>
- Location: <where outputs go in the project>
## Integration Contract
- This WP produces: <what downstream consumers can expect>
- This WP consumes: <what it needs from the project, NOT from other WPs>
## Quality Requirements (MANDATORY)
- Code must compile/parse without errors
- Follow existing project conventions (naming, structure, patterns)
- Run any existing tests related to your changes — do NOT skip tests
- Run the project linter if one exists (eslint, ruff, golangci-lint, etc.)
- No `type: ignore`, `@ts-ignore`, `any` casts, or suppression comments unless the existing code already uses them
- No placeholder code — no `TODO`, `FIXME`, or stub implementations
- Verify your changes work by running or testing them before completing
- If you break existing tests, fix them — do not delete or skip them
## Committing (MANDATORY if you changed any file)
- Commit your work to this package's own branch before you finish. The worktree is removed once
your commit exists and the tree is clean. Uncommitted work is retained for recovery.
- Stage explicit paths. Never `git add -A` or `git add .` — the coordination directory and other
packages' stray files must not enter your commit.
## Dependency Context
- This WP depends on: <list of dependency WP IDs, or "none">
- Outputs from completed dependencies will be provided below when available
INSTREOF
重要: 每个 instructions.md 都必须包含明确的文件路径——并行 Agent 会各自独立解读含糊的范围,因此如果没有明确路径,两个 WP 可能会修改同一个文件,或在它们之间留下缺漏。禁止使用“创建 auth 模块”这类含糊描述——应指定确切路径,例如 src/auth/oauth.ts。
launch.sh
v8.44.0:每个工作包都在自己的 git worktree 中运行,以实现完整的文件隔离。这可避免多个 Agent 同时修改文件时发生写入争用。
cat > ".octo/parallel/WP-N/launch.sh" << 'LAUNCHEOF'
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)"
PROJECT_ROOT="<absolute-project-root-path>"
WP_ID="WP-N"
WP_BRANCH="<wp-branch-name>"
BASE_REF="<base-ref>"
REGISTRY="${HOME}/.claude-octopus/plugin/scripts/agent-registry.sh"
# Every exit path must leave exit-code and .done behind, or the orchestrator's
# monitor loop waits for a marker that never arrives and only the wave timeout
# ends the run.
fail() {
echo "${1}" >&2
if [[ -x "$REGISTRY" ]]; then
"$REGISTRY" update "$WP_ID" --status failed --error "${1}" 2>/dev/null || true
fi
echo "${2:-1}" > "$SCRIPT_DIR/exit-code"
touch "$SCRIPT_DIR/.done"
exit "${2:-1}"
}
# A retry must not inherit the previous run's completion status.
rm -f "$SCRIPT_DIR/.done" "$SCRIPT_DIR/exit-code" || fail "ERROR: cannot clear completion markers"
# Hook environments can otherwise redirect Git away from PROJECT_ROOT.
while IFS= read -r git_var; do unset "$git_var"; done < <(git rev-parse --local-env-vars)
# v8.44.0: Create isolated worktree for this work package.
# Each package checks out its OWN branch. git refuses to check one branch out
# in two worktrees, so reusing the session branch fails every package after the
# first, and a shared branch would also pile unrelated packages onto one ref.
cd "$PROJECT_ROOT" || fail "ERROR: cannot enter $PROJECT_ROOT"
PROJECT_ROOT="$(pwd -P)"
WORKTREE_DIR="${PROJECT_ROOT}/../.octo-worktree-${PROJECT_ROOT##*/}-${WP_ID}"
COMMON_DIR="$(git rev-parse --git-common-dir)" || fail "ERROR: not a Git repository"
COMMON_DIR="$(cd "$COMMON_DIR" && pwd -P)" || fail "ERROR: cannot resolve repository identity"
git worktree prune 2>/dev/null || true
if [[ -d "$WORKTREE_DIR" ]]; then
# Retry: reuse the existing worktree instead of discarding the work in it.
cd "$WORKTREE_DIR" || fail "ERROR: cannot enter $WORKTREE_DIR"
else
git worktree add -b "$WP_BRANCH" "$WORKTREE_DIR" "$BASE_REF" \
> "$SCRIPT_DIR/worktree.log" 2>&1 ||
git worktree add "$WORKTREE_DIR" "$WP_BRANCH" \
>> "$SCRIPT_DIR/worktree.log" 2>&1 ||
fail "ERROR: failed to create worktree at $WORKTREE_DIR (see worktree.log)"
fi
# Reject stale directories from another project, branch, or non-worktree path.
cd "$WORKTREE_DIR" || fail "ERROR: cannot enter $WORKTREE_DIR"
WORKTREE_DIR="$(pwd -P)"
WORKTREE_TOP="$(git rev-parse --show-toplevel)" || fail "ERROR: not a Git worktree"
WORKTREE_TOP="$(cd "$WORKTREE_TOP" && pwd -P)" || fail "ERROR: cannot resolve worktree root"
WORKTREE_COMMON_DIR="$(git rev-parse --git-common-dir)" || fail "ERROR: cannot identify worktree repository"
WORKTREE_COMMON_DIR="$(cd "$WORKTREE_COMMON_DIR" && pwd -P)" || fail "ERROR: cannot resolve worktree repository"
WORKTREE_BRANCH="$(git symbolic-ref --quiet --short HEAD)" || fail "ERROR: worktree has detached HEAD"
[[ "$WORKTREE_TOP" == "$WORKTREE_DIR" && "$WORKTREE_COMMON_DIR" == "$COMMON_DIR" && \
"$WORKTREE_BRANCH" == "$WP_BRANCH" ]] || fail "ERROR: worktree repository or branch does not match this package"
# Register agent in registry
if [[ -x "$REGISTRY" ]]; then
"$REGISTRY" register "$WP_ID" "$WP_BRANCH" "$WORKTREE_DIR" 2>/dev/null || true
fi
cd "$WORKTREE_DIR" || fail "ERROR: cannot enter $WORKTREE_DIR"
unset CLAUDECODE
# v8.32.0: Credential isolation — work packages don't need provider keys
unset OPENAI_API_KEY AGY_AUTH_TOKEN ANTIGRAVITY_API_KEY OPENROUTER_API_KEY PERPLEXITY_API_KEY
# No `set -e` around this call: a non-zero claude -p must still record its exit
# code and .done rather than abort the script before either is written.
claude -p < "$SCRIPT_DIR/instructions.md" > "$SCRIPT_DIR/output.md" 2>"$SCRIPT_DIR/agent.log"
EXIT_CODE=$?
echo $EXIT_CODE > "$SCRIPT_DIR/exit-code"
# Update agent registry with completion status
if [[ -x "$REGISTRY" ]]; then
if [[ "$EXIT_CODE" -eq 0 ]]; then
"$REGISTRY" update "$WP_ID" --status done 2>/dev/null || true
else
"$REGISTRY" update "$WP_ID" --status failed --error "Exit code $EXIT_CODE" 2>/dev/null || true
fi
fi
# Discard the worktree only once its work is committed to the package's branch.
# A force-remove over uncommitted edits destroys everything the package built;
# the commits themselves survive removal, because they are already in the
# shared object store on WP_BRANCH.
UNCOMMITTED="$(git -C "$WORKTREE_DIR" status --porcelain 2>/dev/null)" ||
fail "ERROR: cannot inspect worktree status; retained $WORKTREE_DIR"
COMMITS="$(git -C "$WORKTREE_DIR" rev-list --count "$BASE_REF..HEAD" 2>/dev/null)" ||
fail "ERROR: cannot inspect worktree commits; retained $WORKTREE_DIR"
echo "$COMMITS" > "$SCRIPT_DIR/commit-count"
cd "$PROJECT_ROOT"
if [[ -z "$UNCOMMITTED" && "$COMMITS" -gt 0 ]]; then
git worktree remove "$WORKTREE_DIR" 2>/dev/null ||
fail "ERROR: cannot remove worktree; retained $WORKTREE_DIR"
elif [[ -n "$UNCOMMITTED" ]]; then
echo "KEPT $WORKTREE_DIR: uncommitted work present on $WP_BRANCH" \
>> "$SCRIPT_DIR/agent.log"
else
echo "KEPT $WORKTREE_DIR: no commits beyond $BASE_REF on $WP_BRANCH" \
>> "$SCRIPT_DIR/agent.log"
fi
touch "$SCRIPT_DIR/.done"
LAUNCHEOF
chmod +x ".octo/parallel/WP-N/launch.sh"
必须替换全部三个占位符: 将 <absolute-project-root-path> 替换为项目的实际根目录
(使用 pwd),将 <wp-branch-name> 替换为 WBS 中此工作包自己的分支,将 <base-ref>
替换为每个工作包分支所基于的 ref(通常为 origin/<trunk>,这样各工作包会成为彼此独立的分支,而不是层层叠加在会话分支上)。
Worktree 回退机制: 如果 git worktree 不可用(浅克隆、分离 HEAD),启动脚本会以失败方式安全退出,并记录非零退出码和 .done,因此波次会报告失败,而不是一直挂起。如果 worktree 中仍有未提交的工作,则会保留该 worktree,不会将其移除,并将原因追加到 agent.log 中。
验证门:instructions_written——验证所有说明文件均已存在:
# Count WPs from wbs.json
wp_count=$(python3 -c "import json; print(len(json.load(open('.octo/parallel/wbs.json'))['work_packages']))")
# Verify each WP has instructions.md and launch.sh
missing=0
for i in $(seq 1 "$wp_count"); do
if [[ ! -f ".octo/parallel/WP-$i/instructions.md" ]]; then
echo "MISSING: .octo/parallel/WP-$i/instructions.md"
missing=$((missing + 1))
fi
if [[ ! -f ".octo/parallel/WP-$i/launch.sh" ]]; then
echo "MISSING: .octo/parallel/WP-$i/launch.sh"
missing=$((missing + 1))
fi
done
if [[ "$missing" -eq 0 ]]; then
echo "Instruction files validation: PASSED ($wp_count work packages)"
else
echo "Instruction files validation: FAILED ($missing files missing)"
fi
在所有说明文件验证通过之前,不要继续执行第 6 步。
第 6 步:启动与监控——基于波次执行(必须)
按依赖波次启动工作包。先运行波次 1;只有在波次 1 完成(并注入输出)后才启动波次 2;依此类推。
如果所有 WP 都在波次 1 中(没有依赖项),其行为与原始启动完全相同——向后兼容。
基于波次的启动顺序:
PROJECT_ROOT="$(pwd)"
WBS_FILE=".octo/parallel/wbs.json"
MAX_WAVE=$(python3 -c "import json; wbs=json.load(open('$WBS_FILE')); print(max(wp.get('wave',1) for wp in wbs['work_packages']))")
TIMEOUT=600 # 10 minutes per wave
echo "Executing $MAX_WAVE wave(s)..."
for WAVE in $(seq 1 "$MAX_WAVE"); do
echo ""
echo "=== WAVE $WAVE ==="
echo ""
# Get WPs for this wave
WAVE_WPS=$(python3 -c "
import json
wbs=json.load(open('$WBS_FILE'))
wps=[wp['id'] for wp in wbs['work_packages'] if wp.get('wave',1)==$WAVE]
print(' '.join(wps))
")
# Inject outputs from completed dependency WPs into instructions
for WP_ID in $WAVE_WPS; do
WP_NUM="${WP_ID#WP-}"
WP_DIR=".octo/parallel/$WP_ID"
# Get dependencies for this WP
DEPS=$(python3 -c "
import json
wbs=json.load(open('$WBS_FILE'))
wp=[w for w in wbs['work_packages'] if w['id']=='$WP_ID'][0]
print(' '.join(wp.get('dependencies',[])))
")
if [[ -n "$DEPS" ]]; then
echo "Injecting dependency outputs into $WP_ID..."
echo "" >> "$WP_DIR/instructions.md"
echo "## Outputs from Dependencies" >> "$WP_DIR/instructions.md"
for DEP in $DEPS; do
DEP_DIR=".octo/parallel/$DEP"
if [[ -f "$DEP_DIR/output.md" ]]; then
echo "" >> "$WP_DIR/instructions.md"
echo "### From $DEP:" >> "$WP_DIR/instructions.md"
head -c 4000 "$DEP_DIR/output.md" >> "$WP_DIR/instructions.md"
fi
done
fi
done
# Launch WPs in this wave with 12s stagger
WAVE_COUNT=0
for WP_ID in $WAVE_WPS; do
WP_NUM="${WP_ID#WP-}"
echo "Launching $WP_ID at $(date '+%H:%M:%S')..."
# Clear before background launch, so the monitor cannot see a stale result.
rm -f ".octo/parallel/$WP_ID/.done" ".octo/parallel/$WP_ID/exit-code" || exit 1
bash ".octo/parallel/$WP_ID/launch.sh" &
WP_PID=$!
echo "$WP_PID" > ".octo/parallel/$WP_ID/pid"
echo " $WP_ID launched (PID: $WP_PID)"
WAVE_COUNT=$((WAVE_COUNT + 1))
# 12-second stagger within wave (skip after last)
REMAINING=$(echo "$WAVE_WPS" | wc -w | tr -d ' ')
if [[ "$WAVE_COUNT" -lt "$REMAINING" ]]; then
echo " Waiting 12 seconds before next launch..."
sleep 12
fi
done
# Monitor this wave
START_TIME=$(date +%s)
COMPLETED=0
WAVE_TOTAL=$(echo "$WAVE_WPS" | wc -w | tr -d ' ')
echo "Monitoring Wave $WAVE ($WAVE_TOTAL WPs, timeout: ${TIMEOUT}s)..."
while [[ "$COMPLETED" -lt "$WAVE_TOTAL" ]]; do
COMPLETED=0
for WP_ID in $WAVE_WPS; do
if [[ -f ".octo/parallel/$WP_ID/.done" ]]; then
COMPLETED=$((COMPLETED + 1))
fi
done
ELAPSED=$(( $(date +%s) - START_TIME ))
echo "Wave $WAVE progress: $COMPLETED/$WAVE_TOTAL complete (${ELAPSED}s elapsed)"
if [[ "$ELAPSED" -gt "$TIMEOUT" ]]; then
echo "TIMEOUT: Wave $WAVE did not complete within ${TIMEOUT}s"
break
fi
if [[ "$COMPLETED" -lt "$WAVE_TOTAL" ]]; then
# v8.45.0: Fire reaction engine between poll cycles
REACTIONS="${HOME}/.claude-octopus/plugin/scripts/reactions.sh"
if [[ -x "$REACTIONS" ]]; then
"$REACTIONS" check-all 2>/dev/null || true
fi
sleep 15
fi
done
echo "Wave $WAVE complete: $COMPLETED/$WAVE_TOTAL finished."
done
echo ""
echo "All waves executed."
验证门:processes_launched——验证所有 WP 均存在 PID 文件。
重要: 上述启动和监控命令应通过原生 shell 命令工具运行。你可能需要将它们合并运行,或将监控作为单独的轮询步骤运行。监控循环会一直阻塞,直到每个波次完成或超时。
在所有波次完成之前,不要继续执行第 7 步。
步骤 7:汇总并呈现(必需)
所有工作包完成(或超时)后,汇总结果。
读取所有输出和退出代码:
echo "=== WORK PACKAGE RESULTS ==="
echo ""
FAILED=0
SUCCEEDED=0
for i in $(seq 1 "$WP_COUNT"); do
WP_DIR=".octo/parallel/WP-$i"
if [[ -f "$WP_DIR/exit-code" ]]; then
EXIT_CODE=$(cat "$WP_DIR/exit-code")
else
EXIT_CODE="N/A (not completed)"
fi
if [[ "$EXIT_CODE" == "0" ]]; then
STATUS="SUCCESS"
SUCCEEDED=$((SUCCEEDED + 1))
else
STATUS="FAILED (exit code: $EXIT_CODE)"
FAILED=$((FAILED + 1))
fi
echo "WP-$i: $STATUS"
if [[ -f "$WP_DIR/output.md" ]]; then
OUTPUT_SIZE=$(wc -c < "$WP_DIR/output.md" | tr -d ' ')
echo " Output: $OUTPUT_SIZE bytes"
else
echo " Output: MISSING"
fi
echo ""
done
echo "=== SUMMARY ==="
echo "Total: $WP_COUNT | Succeeded: $SUCCEEDED | Failed: $FAILED"
然后使用 Read 工具读取每个 output.md,并在宣布成功前进行质量检查:
- 读取所有已完成工作包的
output.md文件 - 标记所有失败的工作包(退出代码非零),并附上其
agent.log内容 - 对每个成功的工作包进行质量抽查 — 扫描输出中是否包含:
- 抑制标记(
@ts-ignore、type: ignore、noqa、eslint-disable) - 占位代码(
TODO、FIXME、not implemented、存根函数) - 测试跳过标记(
skip、xit、xdescribe、pytest.mark.skip) - 如发现任何此类内容:标记为 质量警告(不要自动判定失败,但要告知用户)
- 抑制标记(
- 列出所有工作包创建或修改的文件
- 说明需要人工处理的集成点(共享接口、重叠文件)
按以下格式呈现结果:
=== TEAM OF TEAMS - RESULTS ===
Compound Task: <original task>
Work Packages: N total | N succeeded | N failed
WP-1: <name> - [SUCCESS/FAILED]
<summary of what was accomplished>
WP-2: <name> - [SUCCESS/FAILED]
<summary of what was accomplished>
...
Integration Notes:
- <any cross-WP concerns>
- <files that may need reconciliation>
Failed Work Packages (if any):
- WP-X: <error summary from agent.log>
Coordination Files: .octo/parallel/
验证门:all_work_packages_complete — 所有工作包都有 .done 文件,且已检查退出代码。
Agent 注册表摘要(v8.44.0):
# Show agent registry status for this parallel run
REGISTRY="${HOME}/.claude-octopus/plugin/scripts/agent-registry.sh"
if [[ -x "$REGISTRY" ]]; then
echo ""
echo "=== AGENT REGISTRY ==="
"$REGISTRY" list
fi
协调协议目录结构
由此技能创建和管理:
.octo/parallel/
wbs.json # Work Breakdown Structure
WP-1/
instructions.md # Task instructions for this WP
launch.sh # Launch script (runs claude -p)
output.md # Agent output (created by claude -p)
agent.log # Agent stderr log (created by launch.sh)
exit-code # Process exit code (created by launch.sh)
pid # Process ID (created by orchestrator)
.done # Completion marker (created by launch.sh)
WP-2/
...
WP-N/
...
禁止事项(必需 - 不可违反)
- 不能使用宿主子 Agent 工具子 Agent 作为替代 — Task 子 Agent 在隔离沙盒中运行,无法访问插件,因此无法使用 Octopus 质量门、角色设定或提供方编排
- 不能跳过 WBS 分解(步骤 4)— 未经分解,Agent 会收到完整的复合任务,导致输出重叠且缺乏协调
- 不能在没有指令文件的情况下启动(步骤 6 必须在步骤 5 之后)
- 不能跳过启动之间的 12 秒间隔 — 同时启动进程会导致 CPU/内存争用,降低所有 Agent 的性能
- 不能在检查退出代码前宣布成功
- 不能在完成当前步骤前进入下一步
- 不能编写含糊的指令 — 必须明确指定文件路径
- 不能启动超过 10 个工作包 — 超过 10 个后,资源争用和合并复杂性将抵消并行带来的收益
- 不能跳过监控循环 — 不进行监控会导致失败或卡住的 Agent 未被发现,编排器却报告成功
- 不能在依赖波次完成前启动后续波次 — 后续波次会使用前序波次的输出,过早启动会导致 Agent 缺少上下文
- 存在依赖关系时,不能跳过依赖验证
错误处理
如果工作包失败(退出代码非零):
- 读取其
agent.log,了解错误详情 - 向用户说明错误
- 提出单独重试失败工作包
- 不要重新运行已成功的工作包
如果监控超时:
- 报告哪些工作包已完成、哪些尚未完成
- 检查超时的工作包是否仍在运行(检查 PID)
- 提出延长等待时间或终止剩余进程
如果 claude 命令不可用:
- 使用
command -v claude检查 - 告知用户并停止 — 没有 claude CLI 就无法继续
使用示例
示例:身份验证系统
User: /octo:parallel build a full authentication system with OAuth, RBAC, and audit logging
Decomposition:
WP-1: OAuth Integration
- OAuth provider setup (Google, GitHub)
- Token management and refresh
- Callback handlers
Files: src/auth/oauth.ts, src/auth/providers/
WP-2: RBAC Implementation
- Role and permission models
- Authorization middleware
- Role assignment API
Files: src/auth/rbac.ts, src/middleware/authorize.ts
WP-3: Audit Logging
- Audit event model
- Logging middleware
- Audit query API
Files: src/audit/logger.ts, src/audit/events.ts
Each WP runs as independent claude -p with full Octopus plugin.
Results aggregated after all complete.
示例:迁移(批处理方式)
User: /octo:batch migrate all components in src/components/ from class components to functional React with hooks
Decomposition:
WP-1: Form components (src/components/forms/)
WP-2: Layout components (src/components/layout/)
WP-3: Data display components (src/components/tables/, src/components/charts/)
WP-4: Navigation components (src/components/nav/)
Each WP migrates its directory, runs existing tests, fixes any failures.
No overlapping files — safe to merge all results.
示例:并行修复多个问题
User: /octo:parallel fix issue #12, issue #15, and issue #22
Decomposition (after reading each issue):
WP-1: Fix #12 — login redirect loop (src/auth/login.ts)
WP-2: Fix #15 — pagination off-by-one (src/api/pagination.ts)
WP-3: Fix #22 — dark mode toggle not persisting (src/hooks/useTheme.ts)
No file overlaps detected — all three run in Wave 1.
Each WP runs related tests before marking complete.
示例:并行构建独立工具
User: /octo:parallel build a confluence scraper in go, a markdown-to-obsidian converter, a qdrant vectorizer, and a CLI search tool
Decomposition:
WP-1: Confluence scraper (cmd/scraper/) — Wave 1
WP-2: Markdown-to-Obsidian converter (cmd/converter/) — Wave 2 (depends on WP-1 output format)
WP-3: Qdrant vectorizer (cmd/vectorizer/) — Wave 2 (depends on WP-2 output format)
WP-4: CLI search tool (cmd/search/) — Wave 2 (depends on WP-3 schema)
Wave 1 completes first, output format injected into Wave 2 instructions.
Each WP builds, runs go test, and verifies the binary works.