关于 swain-do
swain-do 是用于 Agent 执行跟踪的技能,将抽象计划和任务转换为 tk 命令,并指导任务分解、依赖管理与状态更新。它还规定会话检查、TDD 和完成前验证等执行流程。
主要功能
- 01将计划和任务映射为 tk 工单
- 02管理工单依赖、认领和状态
- 03关联任务与 SPEC 并处理范围偏移
- 04执行会话检查与书签更新
- 05落实 TDD 和完成前验证
适用场景
- 01为 SPEC 拆分实施计划和任务
- 02查看可执行工作并认领工单
- 03跟踪任务进度及关联规格
- 04遇到偏差时升级并协调处理
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cristoslc/ swain --skill swain-do安装后在 Claude Code 中输入/swain-do确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
bin/ticket-migrate-beadsticket-querytkreferences/.gitkeepconfiguration.mdescalation.mdexecution-strategy.mdplan-ingestion.mdreconciliation.mdtdd-enforcement.mdtk-cheatsheet.mdscripts/.gitkeepingest-plan.pyswain-worktree-overlap.shtest-worktree-overlap.sh详细介绍
执行跟踪
进行任何会更改状态的操作之前,请检查是否存在活动会话:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-session-check.sh" 2>/dev/null
如果 JSON 输出中的 "status" 不为 "active",请告知操作员:“没有活动会话 — 要通过 /swain-init 启动一个吗?”如果对方选择忽略,则继续。
用于 Agent 执行跟踪的抽象层。其他技能(例如 swain-design)使用抽象术语表达意图;此技能会将这些意图转换为具体的 CLI 命令。
**首次使用前:**阅读 references/tk-cheatsheet.md,了解完整的命令语法、标志、ID 格式和反模式。
工件交接协议
此技能会根据四级跟踪模型接收来自 swain-design 的交接:
| 层级 | 工件 | 此技能的职责 |
|---|---|---|
| 实现 | SPEC | 在编写任何代码之前,创建有跟踪记录的实现计划和任务拆分 |
| 协调 | EPIC、VISION、JOURNEY | 不直接跟踪 — swain-design 会先将其拆分为子项,然后再移交这些子项 |
| 研究 | SPIKE | 如果研究足够复杂,值得拆分任务,则创建有跟踪记录的计划 |
| 参考 | ADR、PERSONA、RUNBOOK | 无需跟踪 |
如果直接针对协调层级的工件(EPIC、VISION、JOURNEY)调用此技能,且此前尚未进行拆分,则交由 swain-design 先创建子 SPEC,再为这些子项创建计划。
术语映射
其他技能使用以下抽象术语。此技能会将它们映射到当前后端(tk):
| 抽象术语 | 含义 | tk 命令 |
|---|---|---|
| implementation plan | 汇集某个 SPEC 工件所有任务的顶层容器 | tk create "Title" -t epic --external-ref <SPEC-ID> |
| task | 计划中的一个独立工作单元 | tk create "Title" -t task --parent <epic-id> |
| origin ref | 将计划链接到其来源 SPEC 的不可变引用 | 创建 epic 时使用的 --external-ref <ID> 标志 |
| spec tag | 将任务关联到其影响的所有 SPEC 的可变标签 | 创建时使用 --tags spec:<ID> |
| dependency | 任务之间的顺序约束 | tk dep <child> <parent>(child 依赖于 parent) |
| ready work | 可领取且未受阻的任务 | tk ready |
| claim | 原子地取得任务的所有权 | tk claim <id> |
| complete | 将任务标记为已完成 | tk add-note <id> "reason",然后执行 tk close <id> |
| abandon | 关闭不会完成的任务 | tk add-note <id> "Abandoned: <why>",然后执行 tk close <id> |
| escalate | 放弃任务,并调用 swain-design 更新上游工件 | 放弃任务,然后调用 swain-design 技能 |
配置与引导
配置存储在 .agents/execution-tracking.vars.json 中(首次运行时创建)。阅读 references/configuration.md,了解首次运行的设置问题、配置项和 6 步引导工作流。
状态
tk 只接受三种状态值:open、in_progress、closed。使用 status 命令设置任意状态,但依赖关系图(ready、blocked)只会评估这三种状态。
要表示放弃,请使用 tk add-note <id> "Abandoned: ...",然后执行 tk close <id> — 参见升级。
工单生命周期(ADR-015)
工单是临时执行脚手架 — 用于帮助 Agent 在实现 SPEC 期间跟踪工作并恢复进度。父级 SPEC 进入终态(Complete、Abandoned)后,其工单可以丢弃。工单不会提交到 trunk,不用作回顾证据,也不应阻碍工作树清理。会话日志(.agents/session.json JSONL)是事件记录的归档;工单则是当前进度的实时看板。
操作规则
- 创建议题时始终包含
--description(或-d)——仅有标题会丢失任务背后的“原因”。后续接手这项工作的 Agent(或未来的你)需要足够的背景信息,才能采取行动,而不必重新研究。 - 在工作开始时、每个重要里程碑之后以及最终回复之前创建/更新任务——这样,任务跟踪器就能作为实时仪表盘发挥作用,而不是事后记录。
- 任务标题要简短且以行动为导向——它们会显示在
tk ready输出、树状视图和通知中,这些地方的空间有限。 - 使用
tk add-note <id> "context"保存交接备注,而不要依赖临时聊天上下文——会话之间的聊天记录会丢失,但任务备注会保留,并且任何 Agent 或观察者都能看到。 - 在标签中加入相关制品 ID 的引用(例如
spec:SPEC-003)——这样就能查询所有涉及特定规范的工作。 - 关闭未完成的任务时,放弃原因必须以
Abandoned:开头——这一约定便于查找已放弃的工作,避免任务悄然消失。 - 需要结构化输出时使用
ticket-query——需要用于程序处理的 JSON 时,应通过ticket-query(位于 vendoredbin/目录中)进行管道处理,而不要解析人类可读的输出。例如:ticket-query '.status == "open"'
TDD 强制要求
严格执行 RED-GREEN-REFACTOR,并采用反合理化保障机制和完成验证。阅读 references/tdd-enforcement.md,了解反合理化表、任务排序规则和证据要求。
规范溯源标签
在计划 Epic 上使用 --external-ref SPEC-NNN(不可变的源头),在子任务上使用 --tags spec:SPEC-NNN(可变)。查询:ticket-query '.tags and (.tags | contains("spec:SPEC-003"))'。跨计划链接:tk link <task-a> <task-b>。
升级处理
当工作无法按设计继续时,放弃任务并升级给 swain-design。阅读 references/escalation.md,了解分流表、放弃命令、升级工作流和跨规范处理方式。
“接下来做什么?”流程
运行 tk ready 查找未受阻的任务,并运行 ticket-query '.status == "in_progress"' 查找进行中的工作。如果 .tickets/ 为空或不存在,则运行 bash "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/bin/chart.sh" ready,获取制品级指引。
认领任务时的上下文
认领带有 spec:<ID> 标签的任务时,展示 Vision 溯源路径,以提供战略背景。运行 bash "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/bin/chart.sh" scope <SPEC-ID> 2>/dev/null | head -5,显示父级链路。这能让 Agent/操作员了解当前任务与项目战略的关联。
制品/tk 对账
当 specwatch 检测到不匹配(.agents/specwatch.log 中的 TK_SYNC、TK_ORPHAN)时,阅读 references/reconciliation.md,了解不匹配类型、解决命令和对账工作流。
漂移解决(SPEC-307)
创建、编辑或关闭工单时——如果工单带有 spec: 标签——针对该标签指定的 SPEC 运行漂移解决流程。阅读工单和 SPEC。如果工单范围偏离 SPEC 的验收标准或问题陈述,则采取修正措施:要么重新调整子项(编辑工单),要么更新父项(编辑 SPEC)。
修正方向依据信号和内容判断:统计此前针对父项做出的漂移决策(越多表示父项越可能过时),并评估哪个方向能带来更好的结果。应用修正后,将结果提交操作员审核:接受、修改或还原。所有结果都通过 swain-session-state.sh record-decision 记录为漂移决策。
会话书签
执行更改状态的操作后,更新书签:bash "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/bin/swain-bookmark.sh" "<action> <task-description>"
Superpowers 技能链式调用
安装 superpowers 后,swain-do 会在特定环节调用这些技能。跳过这些技能或将相关工作内联,会削弱它们所提供的保障——TDD 会在回归问题累积前将其捕获,验证则可防止错误宣称任务已完成,从而避免浪费后续工作:
-
为任何任务编写代码之前: 调用
test-driven-development技能。先编写一个失败的测试(RED),再让它通过(GREEN),然后重构。此要求适用于每个任务,而不只是第一个任务。 -
分派并行工作时: 如果有可用的子 Agent 且任务彼此独立,则调用
subagent-driven-development;如果按顺序执行,则调用executing-plans。阅读 references/execution-strategy.md 中的决策树。 -
声称任何任务或计划已完成之前: 调用
verification-before-completion。运行验证命令,阅读输出,然后才能确认成功。没有最新证据,不得声称已完成。
检测: ls .agents/skills/test-driven-development/SKILL.md .claude/skills/test-driven-development/SKILL.md 2>/dev/null — 如果至少有一个路径存在,则表示 superpowers 可用。在本次会话中缓存检测结果。
未安装 superpowers 时,swain-do 使用内置的 TDD 强制机制(参见 references/tdd-enforcement.md),并按顺序执行。
计划导入(superpowers 集成)
存在 superpowers 计划文件时,请使用计划导入脚本(scripts/ingest-plan.py),而不是手动拆分任务。阅读 references/plan-ingestion.md,了解用法、格式要求以及不应使用该脚本的情况。
执行策略
根据 superpowers 是否可用以及任务复杂度,选择按顺序执行或由子 Agent 驱动的执行方式。阅读 references/execution-strategy.md,了解决策树、检测命令和 worktree 与产物的映射。
计划前的实现情况检测
为 SPEC 创建计划之前,先扫描是否已有实现证据。这可以避免重复实现尚未合并的分支中已有的工作,或之前会话中已完成的工作。并行运行以下检查——它们是彼此独立的信号,最终会汇总为一个决策。
信号扫描
| 信号 | 检查 | 重要性 |
|---|---|---|
| 未合并分支 | git for-each-ref --format='%(refname:short) %(upstream:trackshort)' refs/heads/ | grep -i "<SPEC-ID>" 然后验证是否已合并:git merge-base --is-ancestor <branch> HEAD | 先前会话留下的 worktree 分支是最强信号——其中包含尚未进入主干的提交。在创建计划的过程中才发现会造成干扰;现在发现则成本很低。 |
| Git 历史 | git log --oneline --all | grep -i "<SPEC-ID>" | 提及 SPEC ID 的提交表明,仓库历史中的某处曾进行过实现。 |
| 交付文件 | 阅读 SPEC,找出其中描述的输出(脚本、模块、配置)。通过 ls 或 Glob 检查这些文件是否存在于 HEAD 中。 | 磁盘上存在文件但没有对应提交,可能表明有未完成或尚未提交的工作。 |
| 测试通过 | 现在重新运行 SPEC 的测试并阅读输出。先前的结果不算证据——只有最新执行的结果才算。 | 这是关键的关卡。Agent 容易找理由认为“之前测试通过了”,却不重新运行。重要原因在于:会话之间的代码变更可能悄无声息地破坏之前通过的测试。 |
决策
- 2 个或更多信号 → 采用追溯关闭流程(如下)
- 1 个信号 → 按常规创建计划;在第一个任务的描述中注明该信号
- 0 个信号 → 按常规流程继续
追溯关闭路径
如果有证据确认此前已完成实现,可跳过完整的任务分解:
- 创建一个跟踪任务:
tk create "Retroactive verification: <SPEC-ID>" -t task --external-ref <SPEC-ID> -d "Verify prior implementation before closing SPEC." - 认领该任务:
tk claim <id> - 运行
verification-before-completion(如果已安装 superpowers),或手动重新运行该规范的测试。 - 如果验证通过:添加包含证据的备注,关闭任务,然后调用 swain-design,将规范状态转换为 Complete。
- 如果验证失败:改为正常创建计划——此前的实现并不完整。
Worktree 隔离前置步骤
swain-do 跟踪的所有变更操作都必须在 worktree 中进行,无论涉及源代码、制品、技能文件还是数据。这样可以避免未完成的变更污染主干,也能防止并行 Agent 之间发生冲突。在执行任何会产生文件变更的操作(创建计划、认领任务、编写代码、编辑制品、更改技能文件、转换规范状态、移交执行)之前,都要进行以下检测:
只读操作可完全跳过此前置步骤——直接在当前上下文中继续。明确允许的只读操作如下:
tk ready、tk show、tk status、tk listticket-query(结构化查询)- 检查计划(读取计划文件,不做修改)
- 状态检查和任务查询
步骤 0 — 提交所有未提交的文件
始终执行此步骤,无论你是在 worktree 中还是在主干上。会话早前产生的未提交变更(新建的制品、编辑过的规范等)必须先提交到 HEAD——worktree 从 HEAD 检出;即使在主干上,未提交文件也有被覆盖或丢失的风险。
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
UNTRACKED=$(git -C "$REPO_ROOT" ls-files --others --exclude-standard 2>/dev/null)
MODIFIED=$(git -C "$REPO_ROOT" diff --name-only 2>/dev/null)
if [ -n "$UNTRACKED" ] || [ -n "$MODIFIED" ]; then
[ -n "$UNTRACKED" ] && echo "$UNTRACKED" | xargs -d '\n' git -C "$REPO_ROOT" add --
[ -n "$MODIFIED" ] && echo "$MODIFIED" | xargs -d '\n' git -C "$REPO_ROOT" add --
git -C "$REPO_ROOT" commit -m "chore: stage dirty tree before worktree creation" || {
echo "ERROR: pre-commit step failed — aborting worktree creation"
exit 1
}
fi
如果提交失败(例如被 pre-commit hook 拒绝),请报告错误并停止。不要继续进行 worktree 检测或任何其他步骤。
步骤 1 — 检测 worktree 上下文
# SPEC-250: Check env var first (set by bin/swain), then git plumbing
if [ -n "${SWAIN_WORKTREE_PATH:-}" ]; then
IN_WORKTREE=yes
else
GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null)
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
[ "$GIT_COMMON" != "$GIT_DIR" ] && IN_WORKTREE=yes || IN_WORKTREE=no
fi
如果 IN_WORKTREE=yes: 已完成隔离。转到步骤 5(worktree 书签)。
如果 IN_WORKTREE=no(主 worktree),且操作将产生文件更改:
-
检查是否存在与目标规范/工作匹配的 worktree:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" bash "$REPO_ROOT/.agents/bin/swain-worktree-overlap.sh" "<SPEC-ID>"如果 JSON 输出包含
"found": true,则询问是否复用:“<SPEC-ID>的 worktree 已存在于<path>。要复用吗?”如果是,告知操作人员使用swain --resume <name>重新启动会话。如果否,告知操作人员使用目的文本启动新会话。 -
worktree 创建由 bin/swain 的启动前流程处理(SPEC-245、EPIC-056)。大多数运行时(Gemini CLI、Codex、Copilot、Crush)无法在会话中途更改工作目录——只有 Claude Code 可以通过
EnterWorktree实现,但这只是特定运行时的权宜之计,并非通用模式。正确的通用方式是通过bin/swain在启动前进行隔离。如果设置了
SWAIN_WORKTREE_PATH,则 Agent 已位于受管理的 worktree 中。如果通过 git plumbing 检测到IN_WORKTREE=yes,则 Agent 位于 worktree 中(可能是手动进入的)。这两种情况下,都继续工作。如果
IN_WORKTREE=no且操作需要隔离,则告知操作人员:“当前不在 worktree 中。使用swain "<purpose>"启动新会话,以启用 worktree 隔离。” -
进入 worktree 后(如果 worktree 刚由 bin/swain 创建),重新运行标签页命名,以反映新的分支:
bash "$REPO_ROOT/.agents/bin/swain-tab-name.sh" --path "$(pwd)" --auto -
记录 worktree 书签(SPEC-235)。进入 worktree 后,调用 swain-bookmark.sh,将其登记到 session.json 中。
WT_PATH="$(pwd)" WT_BRANCH="$(git branch --show-current 2>/dev/null || echo 'unknown')" bash "$REPO_ROOT/.agents/bin/swain-bookmark.sh" worktree add "$WT_PATH" "$WT_BRANCH"
操作人员覆盖设置: 如果操作人员明确表示“在 trunk 上工作”或“不要隔离”,则遵从该设置,在 trunk 上继续。记录警告:“应操作人员要求,正在 trunk 上继续——更改将直接提交到开发分支。”
注意(SPEC-195): swain-init 在启动时不会创建 worktree——worktree 创建延后到此前置流程中,该流程会在 swain-do 分派实际工作时运行。这样可确保 worktree 名称反映工作上下文,并允许检测重叠。
计划中的所有任务完成后,或操作人员提出要求时,在退出 worktree 前运行计划完成交接流程(见下文)。
计划完成与交接
计划 epic 下的所有任务关闭后(或操作人员宣布工作完成时),在退出 worktree 前执行此流程链。这样可确保回顾、SPEC 转换和 EPIC 级联一致触发。
步骤 1 — 检测计划是否完成
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
export PATH="$REPO_ROOT/.agents/bin:$PATH"
# Check if any tasks under the plan epic are still open
OPEN_COUNT=$(ticket-query ".parent == \"<epic-id>\" and .status != \"closed\"" 2>/dev/null | wc -l | tr -d ' ')
如果 OPEN_COUNT > 0,则计划尚未完成——继续工作或询问操作人员。如果 OPEN_COUNT == 0,则继续。
步骤 2 — 运行完成流程管线(SPEC-257)
检测到计划完成后,在转换 SPEC 之前运行质量门控流程管线。这样可确保 BDD 测试、冒烟测试和回顾都自动运行。
2a — 创建完成状态文件
从计划 epic 的 --external-ref 中识别 SPEC ID:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
SPEC_ID=$(tk show <epic-id> 2>/dev/null | grep -i 'external_ref' | awk '{print $NF}')
if [ -z "$SPEC_ID" ]; then
echo "WARNING: No SPEC linked to plan epic — skipping completion pipeline."
fi
如果 SPEC_ID 为空,则完全跳过步骤 2,转到步骤 3。记录警告。
按照 DESIGN-018 创建状态文件:
mkdir -p "$REPO_ROOT/.agents"
jq -n --arg spec "$SPEC_ID" --arg branch "$(git branch --show-current)" \
'{spec_id: $spec, branch: $branch, pipeline_started: (now | todate), steps: {bdd_tests: {status: "pending", timestamp: null, detail: null}, smoke_test: {status: "pending", timestamp: null, detail: null}, retro: {status: "pending", timestamp: null, detail: null}}}' \
> "$REPO_ROOT/.agents/completion-state.json.tmp" \
&& mv "$REPO_ROOT/.agents/completion-state.json.tmp" "$REPO_ROOT/.agents/completion-state.json"
2b — 运行 BDD 测试
检查是否有 swain-test.sh:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
SWAIN_TEST="$REPO_ROOT/.agents/bin/swain-test.sh"
如果存在 swain-test.sh: 运行一次,捕获输出和退出代码:
BDD_OUTPUT=$(bash "$SWAIN_TEST" --artifacts "$SPEC_ID" 2>&1)
BDD_EXIT=$?
- 如果退出代码为 0 → 将状态更新为
passed:BDD_DETAIL=$(echo "$BDD_OUTPUT" | head -5 | tr '\n' ' ') jq --arg status "passed" --arg detail "$BDD_DETAIL" \ '.steps.bdd_tests.status = $status | .steps.bdd_tests.timestamp = (now | todate) | .steps.bdd_tests.detail = $detail' \ "$REPO_ROOT/.agents/completion-state.json" > "$REPO_ROOT/.agents/completion-state.json.tmp" \ && mv "$REPO_ROOT/.agents/completion-state.json.tmp" "$REPO_ROOT/.agents/completion-state.json" - 如果退出代码非 0 → 将状态更新为
failed:
停止流水线。向操作员报告失败:"BDD 测试失败。详情:{detail}。说 retry 可重新运行,或说 skip BDD 可跳过测试并继续。"BDD_DETAIL=$(echo "$BDD_OUTPUT" | tail -10 | tr '\n' ' ') jq --arg status "failed" --arg detail "$BDD_DETAIL" \ '.steps.bdd_tests.status = $status | .steps.bdd_tests.timestamp = (now | todate) | .steps.bdd_tests.detail = $detail' \ "$REPO_ROOT/.agents/completion-state.json" > "$REPO_ROOT/.agents/completion-state.json.tmp" \ && mv "$REPO_ROOT/.agents/completion-state.json.tmp" "$REPO_ROOT/.agents/completion-state.json"
如果不存在 swain-test.sh: 发出警告并标记为已跳过:
jq --arg status "skipped" --arg detail "swain-test.sh not available" \
'.steps.bdd_tests.status = $status | .steps.bdd_tests.timestamp = (now | todate) | .steps.bdd_tests.detail = $detail' \
"$REPO_ROOT/.agents/completion-state.json" > "$REPO_ROOT/.agents/completion-state.json.tmp" \
&& mv "$REPO_ROOT/.agents/completion-state.json.tmp" "$REPO_ROOT/.agents/completion-state.json"
显示:"swain-test 不可用 — 跳过 BDD 门禁。"
2c — 运行冒烟测试
仅当 bdd_tests 为 passed 或 skipped 时继续。如果 bdd_tests 为 failed,流水线已暂停 — 不要运行冒烟测试。
BDD_STATUS=$(jq -r '.steps.bdd_tests.status' "$REPO_ROOT/.agents/completion-state.json")
如果 BDD_STATUS 为 passed 或 skipped:
如果存在 swain-test.sh: swain-test.sh 的冒烟测试输出中包含一个 ## SMOKE 部分,其中列出了手动验证步骤。提取这些步骤并提供给操作员:
SMOKE_SECTION=$(bash "$SWAIN_TEST" --artifacts "$SPEC_ID" 2>&1 | sed -n '/^## SMOKE/,/^## /p' | head -20)
展示冒烟测试说明并请求确认:
冒烟测试说明: {smoke section content}
冒烟测试是否通过?(yes / no / skip)
- yes → 将
smoke_test更新为passed,详情为 "operator confirmed" - no → 将
smoke_test更新为failed,详情使用操作员提供的内容。停止流水线:"冒烟测试失败。说 retry 可重新检查,或说 skip smoke 可继续。" - skip → 将
smoke_test更新为skipped,详情为 "operator chose to skip"
使用 2b 中相同的 jq 更新模式写入状态。
如果不存在 swain-test.sh: 标记为已跳过,详情为 "swain-test.sh not available",与 BDD 回退处理相同。
2d — 运行回顾
仅当 bdd_tests 和 smoke_test 均为 passed 或 skipped 时继续。回顾不可跳过 — 如果操作员说 "skip retro",请拒绝:"回顾始终会运行。即使工作尚不完善,它也能记录经验。"
使用 Agent 的 Skill 工具调用 swain-retro 技能(这是一次工具调用,不是 bash 命令):
使用 Skill 工具:调用
swain-retro,参数为:"SPEC completion — run retro for before phase transition."
swain-retro 完成后,更新状态:
jq --arg status "passed" --arg detail "retro captured" \
'.steps.retro.status = $status | .steps.retro.timestamp = (now | todate) | .steps.retro.detail = $detail' \
"$REPO_ROOT/.agents/completion-state.json" > "$REPO_ROOT/.agents/completion-state.json.tmp" \
&& mv "$REPO_ROOT/.agents/completion-state.json.tmp" "$REPO_ROOT/.agents/completion-state.json"
如果 swain-retro 失败(技能调用出错),将状态更新为 failed 并报告。操作员可以说 retry 重新运行。
2e — 跳过和恢复处理
跳过处理: 在流水线的任何阶段,操作员都可以说:
- "skip BDD" → 将
bdd_tests设为skipped,详情为 "operator requested skip",然后继续执行 2c - "skip smoke" → 将
smoke_test设为skipped,详情为 "operator requested skip",然后继续执行 2d - "skip retro" → 拒绝。回顾始终会运行。请说:"回顾能记录即使不完善的工作的经验 — 不可跳过。"
恢复处理: 如果某一步失败,且操作员说 "retry" 或 "continue":
- 读取
.agents/completion-state.json - 找到第一个状态为
pending或failed的步骤 - 从该步骤恢复流水线 — 不要重新运行已为
passed或skipped的步骤
流水线门禁: 三个步骤全部完成后,验证完成状态:
PENDING=$(jq -r '.steps | to_entries[] | select(.value.status == "pending" or .value.status == "failed") | .key' "$REPO_ROOT/.agents/completion-state.json")
如果 PENDING 为空(所有步骤均为 passed 或 skipped),则继续执行步骤 3(SPEC 转换)。否则,流水线受阻 — 报告仍未完成的步骤。
步骤 3 — 调用 swain-design 进行 SPEC 转换
流水线关卡(SPEC-257): 只有在完成流水线通过后,才能继续进行 SPEC 转换。检查:jq -r '.steps | to_entries[] | select(.value.status == "pending" or .value.status == "failed") | .key' "$REPO_ROOT/.agents/completion-state.json"。如果任何步骤处于 pending 或 failed 状态,请勿转换——返回步骤 2 进行处理。
通过 --external-ref 确定与计划 Epic 关联的 SPEC:
tk show <epic-id> 2>/dev/null # external_ref field contains the SPEC ID
调用 swain-design 以推进 SPEC 阶段。目标阶段取决于 SPEC 当前状态以及验证是否完成:
- 如果所有验收标准都有证据 → 转换到
Complete - 如果验收标准需要手动验证 → 转换到
Needs Manual Test - 如果实现已完成但尚未测试 → 转换到
In Progress(如果尚未处于此状态)
swain-design 会自动处理下游流程:
- 检查父 EPIC 是否也应转换(所有子 SPEC 均已完成 → EPIC Complete)
- 如果 EPIC 到达终止状态 → 调用 swain-retro 进行 EPIC 级回顾(SPEC 级回顾已在步骤 2d 中运行)
步骤 4 — 提议合并和清理
SPEC 转换完成后,提议合并并清理:
所有任务均已关闭。SPEC-NNN 已转换到 {phase}。将此分支合并到 {base-branch} 并清理工作树吗?
如果操作人员接受:
- 确保所有更改都已提交
- 运行
/swain-sync以合并并推送(将锁文件标记为ready_for_cleanup) - 运行时退出后,由 bin/swain 处理工作树清理(SPEC-245)
如果操作人员拒绝,则保留分支。bin/swain 会在下次启动时于菜单中显示该分支。
注意(ADR-015): 工作树中的 .tickets/ 文件是临时脚手架,不应阻碍清理。SPEC 完成后,工单不再具有归档价值。
跳过流程
操作人员可以说“just exit”或“skip the handoff”,以跳过步骤 2–4,直接进入 ExitWorktree。在计划 Epic 上记录备注:tk add-note <epic-id> "Exited without completion handoff"。工作树会保留,供下次会话使用。
注意: 跳过流程意味着未运行完成流水线。如果 .agents/completion-state.json 已创建(步骤 2a 已运行),任何处于 pending 状态的步骤都会继续保持待处理状态。swain-teardown 会检测到这一情况,并在同步前调用缺少的步骤。
书签管理(ADR-023)
书签用于跟踪操作人员正在处理的内容。书签会在会话间保留,以便下次会话从上次进度继续。
设置书签
当操作人员说“bookmark this”“remember where I am”,或在更改状态的操作后:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-bookmark.sh" "<context note>"
根据对话上下文或操作人员明确提供的文本推断备注。如果上下文清晰,无需询问备注。
工作树书签
进入工作树时(已在工作树隔离序言的步骤 5 中处理),会注册该工作树:
bash "$REPO_ROOT/.agents/bin/swain-bookmark.sh" worktree add "$WT_PATH" "$WT_BRANCH"
清除书签
当操作人员说“clear bookmark”或“fresh start”时:
bash "$REPO_ROOT/.agents/bin/swain-bookmark.sh" --clear
决策记录(ADR-023)
当操作人员或 Agent 作出重要决策时(批准 SPEC、选择方案、确定方向),记录该决策:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-session-state.sh" record-decision --note "Approved SPEC-119 implementation approach"
决策会计入会话的决策预算。达到预算上限时,告知操作人员并建议运行 /swain-teardown。
进度日志(ADR-023)
完成任务或达到里程碑后,更新进度日志:
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-progress-log.sh" --digest "$REPO_ROOT/.agents/session-log.jsonl"
这会更新每个已触及 EPIC/Initiative 的 progress.md 和 ## Progress 部分。
回退方案
如果找不到 tk 或其不可用:
- 记录失败原因。
- 在工作目录中改用中性的文本任务清单(JSONL 或 Markdown 检查清单)。
- 使用相同的状态模型(
open、in_progress、blocked、closed),并确保更新对外可见。