name: skill-implementer description: 执行遵循计划的一般实现任务。调用用于一般实现工作。 allowed-tools: Task, Bash, Edit, Read, Write, Read(/tmp/.json), Bash(rm:)
原始上下文(现由子代理加载):
- .opencode/context/core/formats/summary-format.md
- .opencode/context/core/standards/code-patterns.md
原始工具(现由子代理使用):
- Read, Write, Edit, Glob, Grep, Bash
实现器技能
薄包装器,将一般实现委托给 general-implementation-agent 子代理。
重要:此技能实现了技能内部后操作模式。子代理返回后,此技能处理所有后操作(状态更新、工件链接、git提交)后返回。这消除了技能返回和编排器之间的“继续”提示问题。
上下文引用
引用(不要急切加载):
- 路径:
.opencode/context/core/formats/return-metadata-file.md- 元数据文件模式 - 路径:
.opencode/context/core/patterns/postflight-control.md- 标记文件协议 - 路径:
.opencode/context/core/patterns/file-metadata-exchange.md- 文件I/O助手 - 路径:
.opencode/context/core/patterns/jq-escaping-workarounds.md- jq转义模式(问题 #1132)
注意:此技能是带有内部后操作的薄包装器。上下文由委托代理加载。
触发条件
此技能在以下情况下激活:
- 任务语言为“general”、“meta”或“markdown”
- 调用 /implement 命令
- 计划存在且任务准备就绪进行实现
执行流程
阶段 1:输入验证
验证必需输入:
task_number- 必须提供并存在于 state.json 中- 任务状态必须允许实现(planned, implementing, partial)
# 查找任务
task_data=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num)' \
specs/state.json)
# 验证存在
if [ -z "$task_data" ]; then
return error "Task $task_number not found"
fi
# 提取字段
language=$(echo "$task_data" | jq -r '.language // "general"')
status=$(echo "$task_data" | jq -r '.status')
project_name=$(echo "$task_data" | jq -r '.project_name')
description=$(echo "$task_data" | jq -r '.description // ""')
# 验证状态
if [ "$status" = "completed" ]; then
return error "Task already completed"
fi
阶段 2:预操作状态更新
在调用子代理之前,将任务状态更新为“implementing”。
更新 state.json:
jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg status "implementing" \
--arg sid "$session_id" \
'(.active_projects[] | select(.project_number == '$task_number')) |= . + {
status: $status,
last_updated: $ts,
session_id: $sid,
started: $ts
}' specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
更新 TODO.md:使用 Edit 工具将状态标记从 [PLANNED] 更改为 [IMPLEMENTING]。
更新计划文件(如果存在):更新计划元数据中的状态字段:
# 查找最新计划文件
plan_file=$(ls -1 "specs/${padded_num}_${project_name}/plans/implementation-"*.md 2>/dev/null | sort -V | tail -1)
if [ -n "$plan_file" ] && [ -f "$plan_file" ]; then
sed -i 's/^\- \*\*Status\*\*: \[.*\]$/- **Status**: [IMPLEMENTING]/' "$plan_file"
sed -i 's/^\*\*Status\*\*: \[.*\]$/**Status**: [IMPLEMENTING]/' "$plan_file"
fi
阶段 3:创建后操作标记
创建标记文件以防止提前终止:
# 确保任务目录存在
padded_num=$(printf "%03d" "$task_number")
mkdir -p "specs/${padded_num}_${project_name}"
cat > "specs/${padded_num}_${project_name}/.postflight-pending" << EOF
{
"session_id": "${session_id}",
"skill": "skill-implementer",
"task_number": ${task_number},
"operation": "implement",
"reason": "Postflight pending: status update, artifact linking, git commit",
"created": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"stop_hook_active": false
}
EOF
阶段 4:准备委托上下文
为子代理准备委托上下文:
{
"session_id": "sess_{timestamp}_{random}",
"delegation_depth": 1,
"delegation_path": ["orchestrator", "implement", "skill-implementer"],
"timeout": 7200,
"task_context": {
"task_number": N,
"task_name": "{project_name}",
"description": "{description}",
"language": "{language}"
},
"plan_path": "specs/{NNN}_{SLUG}/plans/implementation-{NNN}.md",
"metadata_file_path": "specs/{NNN}_{SLUG}/.return-meta.json"
}
阶段 5:调用子代理
关键:必须使用 Task 工具生成子代理。
必需工具调用:
Tool: Task (NOT Skill)
Parameters:
- subagent_type: "general-implementation-agent"
- prompt: [Include task_context, delegation_context, plan_path, metadata_file_path]
- description: "Execute implementation for task {N}"
不要 使用 Skill(general-implementation-agent) - 这将失败。
子代理将:
- 加载实现上下文文件
- 解析计划并找到恢复点
- 顺序执行阶段
- 根据需要创建/修改文件
- 创建实现摘要
- 将元数据写入
specs/{NNN}_{SLUG}/.return-meta.json - 返回一个简短的文本摘要(不是 JSON)
阶段 5a:验证子代理返回格式
重要:检查子代理是否意外将 JSON 返回到控制台(v1 模式)而不是写入文件(v2 模式)。
如果子代理的文本返回解析为有效 JSON,记录警告:
# 检查子代理返回是否看起来像 JSON(以 { 开头且为有效 JSON)
subagent_return="$SUBAGENT_TEXT_RETURN"
if echo "$subagent_return" | grep -q '^{' && echo "$subagent_return" | jq empty 2>/dev/null; then
echo "WARNING: Subagent returned JSON to console instead of writing metadata file."
echo "This indicates the agent may have outdated instructions (v1 pattern instead of v2)."
echo "The skill will continue by reading the metadata file, but this should be fixed."
fi
此验证:
- 不失败操作(继续读取元数据文件)
- 记录警告以进行调试
- 指示子代理指令需要更新
- 允许混合 v1/v2 代理的优雅处理
阶段 6:解析子代理返回(读取元数据文件)
子代理返回后,读取元数据文件:
metadata_file="specs/${padded_num}_${project_name}/.return-meta.json"
if [ -f "$metadata_file" ] && jq empty "$metadata_file" 2>/dev/null; then
status=$(jq -r '.status' "$metadata_file")
artifact_path=$(jq -r '.artifacts[0].path // ""' "$metadata_file")
artifact_type=$(jq -r '.artifacts[0].type // ""' "$metadata_file")
artifact_summary=$(jq -r '.artifacts[0].summary // ""' "$metadata_file")
phases_completed=$(jq -r '.metadata.phases_completed // 0' "$metadata_file")
phases_total=$(jq -r '.metadata.phases_total // 0' "$metadata_file")
# 提取 completion_data 字段(如果存在)
completion_summary=$(jq -r '.completion_data.completion_summary // ""' "$metadata_file")
claudemd_suggestions=$(jq -r '.completion_data.claudemd_suggestions // ""' "$metadata_file")
roadmap_items=$(jq -c '.completion_data.roadmap_items // []' "$metadata_file")
else
echo "Error: Invalid or missing metadata file"
status="failed"
fi
阶段 7:更新任务状态(后操作)
如果状态是“implemented”:
将 state.json 更新为“completed”并添加 completion_data 字段:
# 步骤 1:更新状态和时间戳
jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg status "completed" \
'(.active_projects[] | select(.project_number == '$task_number')) |= . + {
status: $status,
last_updated: $ts,
completed: $ts
}' specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
# 步骤 2:添加 completion_summary(已完成任务始终需要)
if [ -n "$completion_summary" ]; then
jq --arg summary "$completion_summary" \
'(.active_projects[] | select(.project_number == '$task_number')).completion_summary = $summary' \
specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
fi
# 步骤 3:添加语言特定完成字段
# 对于 meta 任务:添加 claudemd_suggestions
if [ "$language" = "meta" ] && [ -n "$claudemd_suggestions" ]; then
jq --arg suggestions "$claudemd_suggestions" \
'(.active_projects[] | select(.project_number == '$task_number')).claudemd_suggestions = $suggestions' \
specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
fi
# 对于非 meta 任务:添加 roadmap_items(如果存在且非空)
if [ "$language" != "meta" ] && [ "$roadmap_items" != "[]" ] && [ -n "$roadmap_items" ]; then
jq --argjson items "$roadmap_items" \
'(.active_projects[] | select(.project_number == '$task_number')).roadmap_items = $items' \
specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
fi
更新 TODO.md:将状态标记从 [IMPLEMENTING] 更改为 [COMPLETED]。
更新计划文件(如果存在):将状态字段更新为 [COMPLETED] 并验证:
plan_file=$(ls -1 "specs/${padded_num}_${project_name}/plans/implementation-"*.md 2>/dev/null | sort -V | tail -1)
if [ -n "$plan_file" ] && [ -f "$plan_file" ]; then
# 先尝试项目符号模式,然后非项目符号模式
sed -i 's/^\- \*\*Status\*\*: \[.*\]$/- **Status**: [COMPLETED]/' "$plan_file"
sed -i 's/^\*\*Status\*\*: \[.*\]$/**Status**: [COMPLETED]/' "$plan_file"
# 验证更新
if grep -qE '^\*\*Status\*\*: \[COMPLETED\]|^\- \*\*Status\*\*: \[COMPLETED\]' "$plan_file"; then
echo "Plan file status updated to [COMPLETED]"
else
echo "WARNING: Could not verify plan file status update"
fi
else
echo "INFO: No plan file found to update (directory: specs/${padded_num}_${project_name}/plans/)"
fi
如果状态是“partial”:
保持状态为“implementing”但更新恢复点:
jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--argjson phase "$phases_completed" \
'(.active_projects[] | select(.project_number == '$task_number')) |= . + {
last_updated: $ts,
resume_phase: ($phase + 1)
}' specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
TODO.md 保持为 [IMPLEMENTING]。
更新计划文件(如果存在):将状态字段更新为 [PARTIAL] 并验证:
plan_file=$(ls -1 "specs/${padded_num}_${project_name}/plans/implementation-"*.md 2>/dev/null | sort -V | tail -1)
if [ -n "$plan_file" ] && [ -f "$plan_file" ]; then
# 先尝试项目符号模式,然后非项目符号模式
sed -i 's/^\- \*\*Status\*\*: \[.*\]$/- **Status**: [PARTIAL]/' "$plan_file"
sed -i 's/^\*\*Status\*\*: \[.*\]$/**Status**: [PARTIAL]/' "$plan_file"
# 验证更新
if grep -qE '^\*\*Status\*\*: \[PARTIAL\]|^\- \*\*Status\*\*: \[PARTIAL\]' "$plan_file"; then
echo "Plan file status updated to [PARTIAL]"
else
echo "WARNING: Could not verify plan file status update"
fi
else
echo "INFO: No plan file found to update (directory: specs/${padded_num}_${project_name}/plans/)"
fi
失败时:保持状态为“implementing”以重试。不更新计划文件(保持为 [IMPLEMENTING] 以重试)。
阶段 8:链接工件
将工件添加到 state.json 并附带摘要。
重要:使用两步 jq 模式以避免问题 #1132 转义错误。参考 jq-escaping-workarounds.md。
if [ -n "$artifact_path" ]; then
# 步骤 1:过滤掉现有的摘要工件(使用“| not”模式以避免 != 转义 - 问题 #1132)
jq '(.active_projects[] | select(.project_number == '$task_number')).artifacts =
[(.active_projects[] | select(.project_number == '$task_number')).artifacts // [] | .[] | select(.type == "summary" | not)]' \
specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
# 步骤 2:添加新摘要工件
jq --arg path "$artifact_path" \
--arg type "$artifact_type" \
--arg summary "$artifact_summary" \
'(.active_projects[] | select(.project_number == '$task_number')).artifacts += [{"path": $path, "type": $type, "summary": $summary}]' \
specs/state.json > /tmp/state.json && mv /tmp/state.json specs/state.json
fi
更新 TODO.md(如果已实现):添加摘要工件链接。
为 TODO.md 剥离 specs/ 前缀(TODO.md 在 specs/ 内):todo_link_path="${artifact_path#specs/}"
- **Summary**: [implementation-summary-{DATE}.md]({todo_link_path})
阶段 9:Git 提交
使用会话 ID 提交更改:
git add -A
git commit -m "task ${task_number}: complete implementation
Session: ${session_id}
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
阶段 10:清理
删除标记和元数据文件:
rm -f "specs/${padded_num}_${project_name}/.postflight-pending"
rm -f "specs/${padded_num}_${project_name}/.postflight-loop-guard"
rm -f "specs/${padded_num}_${project_name}/.return-meta.json"
阶段 11:返回简要摘要
返回一个简短的文本摘要(不是 JSON)。示例:
Implementation completed for task {N}:
- All {phases_total} phases executed successfully
- Key changes: {summary of changes}
- Created summary at specs/{NNN}_{SLUG}/summaries/implementation-summary-{DATE}.md
- Status updated to [COMPLETED]
- Changes committed
错误处理
输入验证错误
如果任务未找到或状态无效,立即返回错误消息。
元数据文件缺失
如果子代理未写入元数据文件:
- 保持状态为“implementing”
- 不清理后操作标记
- 向用户报告错误
Git 提交失败
非阻塞:记录失败但继续成功响应。
子代理超时
如果子代理超时(默认 7200 秒),返回部分状态。 保持状态为“implementing”以恢复。
返回格式
此技能返回一个简短文本摘要(不是 JSON)。JSON 元数据写入文件并在内部处理。
示例成功返回:
Implementation completed for task 350:
- All 5 phases executed successfully
- Created new feature component with tests
- Created summary at specs/350_feature/summaries/implementation-summary-20260118.md
- Status updated to [COMPLETED]
- Changes committed with session sess_1736700000_abc123
示例部分返回:
Implementation partially completed for task 350:
- Phases 1-3 of 5 executed
- Phase 4 failed: TypeScript compilation error
- Partial summary at specs/350_feature/summaries/implementation-summary-20260118.md
- Status remains [IMPLEMENTING] - run /implement 350 to resume