mcpField
S
swain-do

swain-do

github.com/cristoslcAgent 工作流2128 次安装25 周前更新
代码仓库

关于 swain-do

swain-do 是用于 Agent 执行跟踪的技能,将抽象计划和任务转换为 tk 命令,并指导任务分解、依赖管理与状态更新。它还规定会话检查、TDD 和完成前验证等执行流程。

主要功能

  1. 01将计划和任务映射为 tk 工单
  2. 02管理工单依赖、认领和状态
  3. 03关联任务与 SPEC 并处理范围偏移
  4. 04执行会话检查与书签更新
  5. 05落实 TDD 和完成前验证

适用场景

  1. 01为 SPEC 拆分实施计划和任务
  2. 02查看可执行工作并认领工单
  3. 03跟踪任务进度及关联规格
  4. 04遇到偏差时升级并协调处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cristoslc/swain --skill swain-do

安装后在 Claude Code 中输入/swain-do确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

bin/
ticket-migrate-beads
ticket-query
tk
references/
.gitkeep
configuration.md
escalation.md
execution-strategy.md
plan-ingestion.md
reconciliation.md
tdd-enforcement.md
tk-cheatsheet.md
scripts/
.gitkeep
ingest-plan.py
swain-worktree-overlap.sh
test-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)是事件记录的归档;工单则是当前进度的实时看板。

操作规则

  1. 创建议题时始终包含 --description(或 -d)——仅有标题会丢失任务背后的“原因”。后续接手这项工作的 Agent(或未来的你)需要足够的背景信息,才能采取行动,而不必重新研究。
  2. 在工作开始时、每个重要里程碑之后以及最终回复之前创建/更新任务——这样,任务跟踪器就能作为实时仪表盘发挥作用,而不是事后记录。
  3. 任务标题要简短且以行动为导向——它们会显示在 tk ready 输出、树状视图和通知中,这些地方的空间有限。
  4. 使用 tk add-note <id> "context" 保存交接备注,而不要依赖临时聊天上下文——会话之间的聊天记录会丢失,但任务备注会保留,并且任何 Agent 或观察者都能看到。
  5. 在标签中加入相关制品 ID 的引用(例如 spec:SPEC-003)——这样就能查询所有涉及特定规范的工作。
  6. 关闭未完成的任务时,放弃原因必须以 Abandoned: 开头——这一约定便于查找已放弃的工作,避免任务悄然消失。
  7. 需要结构化输出时使用 ticket-query——需要用于程序处理的 JSON 时,应通过 ticket-query(位于 vendored bin/ 目录中)进行管道处理,而不要解析人类可读的输出。例如: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 会在回归问题累积前将其捕获,验证则可防止错误宣称任务已完成,从而避免浪费后续工作:

  1. 为任何任务编写代码之前: 调用 test-driven-development 技能。先编写一个失败的测试(RED),再让它通过(GREEN),然后重构。此要求适用于每个任务,而不只是第一个任务。

  2. 分派并行工作时: 如果有可用的子 Agent 且任务彼此独立,则调用 subagent-driven-development;如果按顺序执行,则调用 executing-plans。阅读 references/execution-strategy.md 中的决策树。

  3. 声称任何任务或计划已完成之前: 调用 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 个信号 → 按常规流程继续
追溯关闭路径

如果有证据确认此前已完成实现,可跳过完整的任务分解:

  1. 创建一个跟踪任务:tk create "Retroactive verification: <SPEC-ID>" -t task --external-ref <SPEC-ID> -d "Verify prior implementation before closing SPEC."
  2. 认领该任务:tk claim <id>
  3. 运行 verification-before-completion(如果已安装 superpowers),或手动重新运行该规范的测试。
  4. 如果验证通过:添加包含证据的备注,关闭任务,然后调用 swain-design,将规范状态转换为 Complete。
  5. 如果验证失败:改为正常创建计划——此前的实现并不完整。

Worktree 隔离前置步骤

swain-do 跟踪的所有变更操作都必须在 worktree 中进行,无论涉及源代码、制品、技能文件还是数据。这样可以避免未完成的变更污染主干,也能防止并行 Agent 之间发生冲突。在执行任何会产生文件变更的操作(创建计划、认领任务、编写代码、编辑制品、更改技能文件、转换规范状态、移交执行)之前,都要进行以下检测:

只读操作可完全跳过此前置步骤——直接在当前上下文中继续。明确允许的只读操作如下:

  • tk ready、tk show、tk status、tk list
  • ticket-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),且操作将产生文件更改:

  1. 检查是否存在与目标规范/工作匹配的 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> 重新启动会话。如果否,告知操作人员使用目的文本启动新会话。

  2. 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 隔离。”

  3. 进入 worktree 后(如果 worktree 刚由 bin/swain 创建),重新运行标签页命名,以反映新的分支:

    bash "$REPO_ROOT/.agents/bin/swain-tab-name.sh" --path "$(pwd)" --auto
    
  4. 记录 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=$(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"
    
    停止流水线。向操作员报告失败:"BDD 测试失败。详情:{detail}。说 retry 可重新运行,或说 skip BDD 可跳过测试并继续。"

如果不存在 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":

  1. 读取 .agents/completion-state.json
  2. 找到第一个状态为 pending 或 failed 的步骤
  3. 从该步骤恢复流水线 — 不要重新运行已为 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} 并清理工作树吗?

如果操作人员接受:

  1. 确保所有更改都已提交
  2. 运行 /swain-sync 以合并并推送(将锁文件标记为 ready_for_cleanup)
  3. 运行时退出后,由 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 或其不可用:

  1. 记录失败原因。
  2. 在工作目录中改用中性的文本任务清单(JSONL 或 Markdown 检查清单)。
  3. 使用相同的状态模型(open、in_progress、blocked、closed),并确保更新对外可见。

评论

支持 Markdown