关于 blueprint-feature-tracker-sync
blueprint-feature-tracker-sync 用于协调项目功能跟踪器与 TODO.md,并更新进度信息。它支持只读摘要、差异处理,以及从 taskwarrior sidecar 转移已完成任务。
主要功能
- 01同步跟踪器与 TODO.md
- 02生成只读进度摘要
- 03转移已完成的任务项
- 04重新计算功能统计
- 05更新跟踪器和任务注册表
适用场景
- 01同步 TODO 复选框与功能状态
- 02不修改文件地汇总项目进度
- 03关闭 sidecar 中已完成任务
- 04刷新完成度统计
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill blueprint-feature-tracker-sync安装后在 Claude Code 中输入/blueprint-feature-tracker-sync确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
REFERENCE.mdscripts/blueprint-feature-tracker-sync.shscripts/tests/test-blueprint-feature-tracker-sync.sh详细介绍
将功能跟踪器 JSON 与 TODO.md 同步,并管理任务进度。
何时使用此技能
| 在以下情况下使用此技能…… | 在以下情况下改用 blueprint-feature-tracker-status…… |
|---|---|
| 你要核对 TODO.md 中的复选框与跟踪器 | 你只想查看完成情况统计 |
你要从 taskwarrior sidecar 中清空 WO 条目(--drain-wave) | 你想查看 PRD 覆盖情况或待开始任务列表 |
| 你要在完成工作后重新计算完成情况统计 | 对于低级别的 FR 代码编辑,请改用 feature-tracking |
你想通过 --summary 生成 Markdown 进度摘要 | 你只需快速了解当前进度,且不需要写入文件 |
注意:从 v1.1.0 起,feature-tracker.json 是进度跟踪的唯一真实来源。tasks 部分取代了 work-overview.md。
用法:/blueprint:feature-tracker-sync [--summary] [--drain-wave WO-A,WO-B,...] [--evidence-files <list>] [--evidence <text>]
标志:
| 标志 | 说明 |
|---|---|
--summary | 生成便于阅读的 Markdown 摘要(仅输出到 stdout,不写入文件) |
--drain-wave WO-A,WO-B,... | Sidecar 模式:将 tasks.pending 中逗号分隔列表里的已完成 WO 清空到 tasks.completed,然后将 implementing_wos 中的 WO 均已关闭的 FR 标记为完成 |
--evidence-files <list> | 逗号分隔的文件列表(每个 WO 对应一个文件),用于存放 --drain-wave 的证据字符串。按位置与 WO 列表配对 |
--evidence <text> | 内联证据字符串(仅适用于单个 WO)。文本较短且不含单引号时使用 |
交互模式
在任何结束时的 AskUserQuestion 菜单之前,先解析自动化配置:
bash "${CLAUDE_SKILL_DIR}/../../scripts/get-automation-config.sh"
当 EFFECTIVE_INTERACTION_MODE=quiet 且本次调用由自动化触发(autopilot、session bookend、drift-nudge 后续调用,而非用户输入的斜杠命令)时,跳过结束导航菜单(例如“接下来做什么?”/“再创建一个?”),采用安全默认操作,并以一行回执结束。安静模式绝不会跳过保护写入操作的确认关卡——它只会跳过导航菜单。用户直接调用时始终采用完整交互模式(明确意图优先于安静模式;参见 ADR-0020)。
模式选择(首先执行)
在开始任何工作之前,先判断适用的模式:
- 如果存在
--summary,则运行 模式:生成摘要 并退出。 - 如果存在
--drain-wave,则运行 模式:Taskwarrior Sidecar 清空 并退出。 - 否则,执行 sidecar 检测(下方步骤 0)。如果检测到 sidecar 且
TODO.md不存在,则在面向用户的完成提示中优先采用 Sidecar 清空 语义;否则运行 模式:完整同步(默认)。
模式:生成摘要(--summary)
提供 --summary 时,生成便于阅读的进度报告,不修改任何文件:
jq -r '
"# Work Overview: \(.project)\n\n" +
"## Current Phase: \(.current_phase // "Not set")\n\n" +
"**Progress**: \(.statistics.complete)/\(.statistics.total_features) features (\(.statistics.completion_percentage)%)\n\n" +
"### In Progress\n" +
(if (.tasks.in_progress | length) == 0 then "- (none)\n" else (.tasks.in_progress | map("- \(.description) [\(.id)]") | join("\n")) + "\n" end) +
"\n### Pending\n" +
(if (.tasks.pending | length) == 0 then "- (none)\n" else (.tasks.pending | map("- \(.description) [\(.id)]") | join("\n")) + "\n" end) +
"\n### Recently Completed\n" +
(if (.tasks.completed | length) == 0 then "- (none)\n" else (.tasks.completed | map("- \(.description) [\(.id)]") | join("\n")) + "\n" end) +
"\n## Phase Status\n" +
(.phases | map("- \(.name): \(.status)") | join("\n"))
' docs/blueprint/feature-tracker.json
输出示例:
# Work Overview: my-project
## Current Phase: phase-1
**Progress**: 22/42 features (52.4%)
### In Progress
- Implement OAuth integration [FR2.3]
- Add rate limiting [FR3.1]
### Pending
- Webhook support [FR4.1]
- Admin dashboard [FR5.1]
### Recently Completed
- User authentication [FR2.1]
- Session management [FR2.2]
## Phase Status
- Foundation: complete
- Core Features: in_progress
- Advanced Features: not_started
显示摘要后退出。
模式:完整同步(默认)
Step 0: 运行确定性核心
运行辅助程序。它负责机械化核心工作:检测 taskwarrior-sidecar 标记(SIDECAR=)、检查追踪器是否存在及有效、回填实现证据(文件是否存在 + 使用 git log 对提交去重)、通过固定决策表推断状态,并应用不可降级保护(EVIDENCE_FLIPPED=、status_inferred 问题),以及汇总统计数据(STAT_*、COMPLETION_PERCENTAGE=)。它会原地写入回填后的追踪器:
bash "${CLAUDE_SKILL_DIR}/scripts/blueprint-feature-tracker-sync.sh" --home-dir "$HOME" --project-dir "$(pwd)"
从输出中解析 STATUS= 和 ISSUES:。STATUS=ERROR 表示追踪器缺失(tracker_missing → 报告“未启用功能追踪;请运行 /blueprint:init”)或 JSON 无效。SIDECAR=true 表示正在使用 taskwarrior-sidecar 约定——还要通过可安全并行执行的 export | jq 习惯用法,探查是否存在实时的 taskwarrior 关联(是否有任何任务的 bpid 与项目蓝图 ID 匹配)(task bpid.any: status:any export | jq 'length',绝不要用 task list;参见 .claude/rules/parallel-safe-queries.md)。如果正在使用 sidecar,请跳过 TODO.md 核对步骤(步骤 4–5、8)——不存在权威的 TODO 文件——并将任何 WO 关闭操作转交给 Mode: Taskwarrior Sidecar Drain。
每个 status_inferred 问题都表示证据将某项功能的状态从 not_started 向上调整(保护机制绝不会降低更高的状态);请在步骤 9 报告的“根据证据推断”部分列出这些问题。有关规范的合并 jq 和测试证据模式,请参阅 REFERENCE.md。
Step 4: 检测差异
查找不一致之处:
- 追踪器中标记为
complete的功能,在 TODO.md 中却未勾选 - TODO.md 中已勾选的功能,在追踪器中却未标记为
complete tasks.in_progress中的功能,在追踪器中却标记为complete- PRD 状态与功能实现状态不符
- 标记为
not_started的功能,但步骤 3b 推断有已发布代码(通过步骤 5 确认)
Step 5: 询问用户如何处理差异
如果发现差异(使用 AskUserQuestion):
question: "Found {N} discrepancies. How should they be resolved?"
options:
- label: "Update tracker from TODO.md"
description: "Trust TODO.md, update tracker to match"
- label: "Update TODO.md from tracker"
description: "Trust the tracker, update TODO.md to match"
- label: "Review each discrepancy"
description: "Show each discrepancy and decide individually"
- label: "Skip - don't resolve discrepancies"
description: "Report discrepancies but don't change anything"
Step 6: 重新计算统计数据
功能级别的计数和完成百分比已包含在步骤 0 脚本输出中(STAT_COMPLETE/STAT_PARTIAL/STAT_IN_PROGRESS/STAT_NOT_STARTED/STAT_BLOCKED、COMPLETION_PERCENTAGE)。如果步骤 5 中解决差异后有状态发生变化,则根据所包含的功能重新推导阶段状态:
- 如果所有功能均已完成,则为
complete - 如果任何功能处于
in_progress,则为in_progress - 如果部分功能已完成、部分未完成,则为
partial - 如果没有任何功能已开始,则为
not_started
步骤 6a:解析项目组合链接(v3.3.0+,仅限根蓝图)
仅当根目录中的清单满足 workspaces.role == "root",且
feature-tracker 至少包含一个 implemented_by 数组非空的功能时运行。
-
对于每个包含
implemented_by的功能:-
对每个
{workspace, ref}条目,读取<workspace>/docs/blueprint/feature-tracker.json并查找ref。 -
收集子项状态。如果任何条目无法解析(文件缺失或 ref 缺失),记录一条警告,并在汇总时将该条目视为
not_started。 -
使用以下规则推导根功能的
status:观察到的子项状态 推导出的状态 所有已解析条目均为 completecomplete任意条目为 blockedblocked任意条目为 in_progress,或complete/not_started混合出现partial所有条目均为 not_startednot_started -
将功能的
status覆盖为推导出的值。不要修改项目组合功能上的implementation;只重新计算状态。
-
-
通过读取每个子项的
statistics块,重建顶层的workspaces摘要:"workspaces": { "projects/esp32-lamp": { "total": 14, "complete": 6, "completion_percentage": 42.9, "current_phase": "phase-1", "last_synced_at": "<now>" } } -
应用推导出的状态后,重新计算根目录的
statistics,使项目组合级别的总数 反映由子项驱动的状态。 -
在同步报告(步骤 9)中,对无法解析的
implemented_by条目发出警告;如果被引用的工作区不在根清单的workspaces.children中, 建议使用/blueprint:workspace-scan。
步骤 7:更新 feature-tracker.json
- 应用已解决的差异
- 更新
statistics部分 - 将
last_updated更新为今天的日期 - 如果功能发生变化,则更新 PRD 状态
- 将
current_phase更新为第一个未完成的阶段
步骤 8:更新 TODO.md(如果存在)
- 确保复选框状态与功能状态一致
- 对于
complete功能,使用[x] - 对于
not_started功能,使用[ ] - 如有需要,在任务文本中注明部分完成情况
步骤 9:输出同步报告
打印:统计信息块(total/complete/partial/in_progress/not_started/blocked + 完成百分比)、当前阶段、阶段状态列表、活动任务列表、 “所做更改”(状态切换、修改过的 TODO 复选框)、“根据证据推断”(步骤 3b 中的切换及其提交 SHA),以及“未解决的差异”(如有跳过的项)。完整报告模板请参阅 REFERENCE.md。
步骤 10:更新任务注册表
更新 docs/blueprint/manifest.json 中的任务注册表条目:
jq --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg todo_hash "$(sha256sum TODO.md 2>/dev/null | cut -d' ' -f1)" \
--argjson processed "${FEATURES_SYNCED:-0}" \
'.task_registry["feature-tracker-sync"].last_completed_at = $now |
.task_registry["feature-tracker-sync"].last_result = "success" |
.task_registry["feature-tracker-sync"].context.last_todo_hash = $todo_hash |
.task_registry["feature-tracker-sync"].stats.runs_total = ((.task_registry["feature-tracker-sync"].stats.runs_total // 0) + 1) |
.task_registry["feature-tracker-sync"].stats.items_processed = $processed' \
docs/blueprint/manifest.json > tmp.json && mv tmp.json docs/blueprint/manifest.json
步骤 11:提示下一步操作
使用 AskUserQuestion:
question: "Sync complete. What would you like to do next?"
options:
- label: "View detailed status"
description: "Run /blueprint:feature-tracker-status for full breakdown"
- label: "Continue development"
description: "Run /project:continue to work on next task"
- label: "I'm done"
description: "Exit sync"
模式:Taskwarrior 旁路任务清理(--drain-wave)
将一个或多个已完成的 WO 从 tasks.pending 清理至
tasks.completed,证据来源为 Taskwarrior 注释(或指定文件/
内联字符串),然后切换其实现 WO 均已关闭的任何 FR 级条目。
步骤 1:解析波次列表
按逗号拆分 --drain-wave。对于每个 WO ID,按以下优先顺序匹配相应的证据
来源:
--evidence-files中对应位置的条目(文件路径),使用jq --rawfile读取,以避免单引号冲突。--evidence(仅限单 WO 清理)。- 链接的 Taskwarrior 任务中最新的
annotate行(步骤 2)。 - 最后,如果以上方式均不可用,则使用
AskUserQuestion提示用户提供证据。
如果同时提供了 WO 列表和 --evidence-files 列表,但两者长度不一致,
则明确说明原因并拒绝运行——部分清理比不清理更糟糕。
步骤 2:从 taskwarrior 获取证据
对于此波次中的每个 WO,获取最新注释。使用支持并行的
export | jq 惯用写法——绝不要使用 task list——这样在任务不存在时会返回
退出码 0,不会取消同级工具调用(参见
.claude/rules/parallel-safe-queries.md):
task bpid:"$WO" status:completed export \
| jq -r '.[0].annotations | sort_by(.entry) | last | .description // empty'
如果结果为空,则回退到 status:any(用户可能在排空前关闭了
任务)。如果仍为空,则回退到步骤 1 中的下一个优先级来源。
将每条证据字符串保存到临时文件(mktemp)中——提交消息中嵌入的单引号会与内联到 jq
程序字面量中的内容冲突,而 --rawfile 是标准的转义方式:
ev_file="$(mktemp)"
printf '%s' "$EVIDENCE_STRING" > "$ev_file"
步骤 3:将待处理项排空至已完成
对于此波次中的每个 WO-NNN,使用其证据文件 $ev_file,通过每个 WO 一次
jq 处理来推进跟踪器。将日期存储一次并作为参数传入,以便每个条目都写入相同的值:
today="$(date -u +%Y-%m-%d)"
jq --arg id "$WO" \
--arg today "$today" \
--rawfile ev "$ev_file" '
.tasks.completed = (
[ .tasks.pending[]
| select(.id == $id)
| . + {"completed": $today, "evidence": $ev}
] + .tasks.completed
)
| .tasks.pending = [.tasks.pending[] | select(.id != $id)]
' docs/blueprint/feature-tracker.json > docs/blueprint/feature-tracker.json.tmp
mv docs/blueprint/feature-tracker.json.tmp docs/blueprint/feature-tracker.json
按顺序循环处理 WOs——每次处理都读取上一次写入的文件——这样并发写入就不会在同一个文件上发生冲突。
如果某个 WO ID 不在 tasks.pending 中,则为该条目报告 skipped: not pending,
然后继续。不要因此报错并中止整个波次。
步骤 4:当所有实现中的 WO 均已关闭时,切换 FR 状态
对于 implementing_wos 数组与已排空波次重叠的每项功能,重新计算其
status。该切换是用户每个波次都会重复使用的第二种手动 jq 模式;在此处一次完成:
jq --arg today "$today" '
(.features // [])
|= map(
if (.implementing_wos // []) | length > 0 then
. as $fr
| (.implementing_wos
| map(. as $woid
| (($fr | .. | objects | select(has("id")) | select(.id == $woid))
// null)
| . != null)) as $resolved
| (((.implementing_wos | length) > 0)
and ([.implementing_wos[] as $wo
| any(($fr.parent_tracker.tasks.completed // [])[]; .id == $wo)]
| all)) as $all_done
| if $all_done and (.status // "") != "complete"
then . + {"status": "complete", "completed_at": $today}
else .
end
else .
end
)
' docs/blueprint/feature-tracker.json > docs/blueprint/feature-tracker.json.tmp
mv docs/blueprint/feature-tracker.json.tmp docs/blueprint/feature-tracker.json
如果跟踪器架构将功能存储在扁平的 features 数组中,但形状不同(例如嵌套在
phases[].features[] 下),请调整路径前缀,同时保留相同逻辑:仅当
implementing_wos 中列出的所有 WO ID 都出现在
tasks.completed 中时,功能才会切换为 complete。
在运行报告(步骤 6)中记录每次切换。绝不要静默地将已处于 complete 状态的 FR 降级。
步骤 5:重新计算统计信息
重新运行**模式:完整同步(默认)**中的步骤 6,使总数反映已排空的 WOs 以及任何已切换的 FR。然后按照完整同步的步骤 7 更新 last_updated 和 current_phase。
步骤 6:报告
打印排空报告:
Sidecar Drain Report
====================
Wave: WO-031, WO-032, WO-033
Drained:
- WO-031: pending -> completed (evidence: 142 chars from tw annotation)
- WO-032: pending -> completed (evidence: 209 chars from /tmp/wo032_ev.txt)
- WO-033: skipped (not in tasks.pending)
FR flips:
- FR-017 (Skill Progression): in_progress -> complete
Statistics:
- Total Features: 42
- Complete: 23 (54.8%) [+1 from FR-017]
- Recently Completed: WO-031, WO-032 added to top of tasks.completed
Next: run /taskwarrior:task-done if any sibling tasks should also close.
使用 rm -f "$ev_file" 清理临时证据文件。
单个 WO 简短形式
对于常见的单个 WO 情况,使用 --drain-wave WO-031,并搭配
--evidence "<text>" 或不带证据标志(自动从注释获取证据),整个流程比传统的手写
jq 单行命令更简短——并且生成相同的磁盘数据结构。如果还需要关闭关联的 taskwarrior 任务,请优先使用 /taskwarrior:task-done;此技能仅会编辑跟踪器。
直接编辑与示例输出
如需临时修改跟踪器(用于向 in_progress 添加内容、完成任务、将工作加入待处理队列的 jq 配方)以及示例摘要报告,请参阅 REFERENCE.md。
相关内容
taskwarrior-plugin:task-done— 关闭单个 taskwarrior 任务并排空关联的跟踪器条目;适用于一次有多个 WO 完成的波次,与此技能的--drain-wave搭配使用。taskwarrior-plugin:task-coordinate— 在开始一个波次前列出接下来 N 个无阻塞任务,使你最终在此处排空的 WOs 与队列实际安排的内容一致。session-plugin:session-end— 会话收尾协调器在调查发现已关闭且关联 WO(bpid)的 taskwarrior 任务仍留在跟踪器的tasks.pending中时,会提供--drain-wave处理,以便在会话结束时排空,而不是一直搁置,直到有人想起来手动运行此同步。.claude/rules/parallel-safe-queries.md— 此技能查询 taskwarrior 时,必须使用task ... export | jq惯用写法。task list在结果为空时会以退出码 1 结束,并静默取消同级并行工具调用。