mcpField
B
blueprint-feature-tracker-sync

blueprint-feature-tracker-sync

github.com/laurigates開発5958 回インストール1 日前に更新
リポジトリ

blueprint-feature-tracker-sync について

blueprint-feature-tracker-sync は、プロジェクトの機能トラッカーと TODO.md を照合し、進捗情報を更新するスキルです。読み取り専用の要約、差異の解決、taskwarrior sidecar の完了項目の移行に対応します。

主な機能

  1. 01トラッカーと TODO.md の同期
  2. 02読み取り専用の進捗要約
  3. 03完了した作業項目の移行
  4. 04機能統計の再計算
  5. 05トラッカーとタスクレジストリの更新

活用シーン

  1. 01TODO のチェック状態と機能ステータスの同期
  2. 02ファイルを変更せずに進捗を要約
  3. 03sidecar の完了タスクをクローズ
  4. 04完了率統計の更新

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/laurigates/claude-plugins --skill blueprint-feature-tracker-sync

インストール後、Claude Code で/blueprint-feature-tracker-syncを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

REFERENCE.md
scripts/
blueprint-feature-tracker-sync.sh
scripts/tests/
test-blueprint-feature-tracker-sync.sh

詳細

機能トラッカーの JSON を TODO.md と同期し、タスクの進捗を管理します。

このスキルを使用する場面

次の場合にこのスキルを使用します…次の場合は blueprint-feature-tracker-status を使用します…
TODO.md のチェックボックスとトラッカーの内容を照合する場合完了状況の統計を読み取り専用で確認する場合
taskwarrior のサイドカーから 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 サマリーを生成します(標準出力のみ、ファイルは作成しません)
--drain-wave WO-A,WO-B,...サイドカーモード:tasks.pending から完了した WO のカンマ区切りリストを tasks.completed に移し、implementing_wos がすべて完了した FR のステータスを更新します
--evidence-files <list>--drain-wave のエビデンス文字列を含むファイル(WO ごとに 1 つ)のカンマ区切りリストです。WO のリストと位置順に対応します
--evidence <text>インラインのエビデンス文字列です(WO が 1 つの場合のみ)。テキストが短く、シングルクォートを含まない場合に使用します

インタラクションモード

終了時の AskUserQuestion メニューを表示する前に、自動化設定を解決します。

bash "${CLAUDE_SKILL_DIR}/../../scripts/get-automation-config.sh"

EFFECTIVE_INTERACTION_MODE=quiet であり、かつこの実行が自動化によって開始された場合(autopilot、セッションの締め処理、drift-nudge のフォローアップなど。ユーザーが入力したスラッシュコマンドは除く)、終了時のナビゲーションメニュー(「次は何をしますか?」/「もう 1 つ作成しますか?」形式のメニュー)を省略し、安全なデフォルトを適用して、1 行の処理結果を出力して終了します。quiet モードで省略されるのはナビゲーションメニューのみで、書き込みを保護する確認ゲートは省略しません。ユーザーが直接実行した場合は常に完全な対話形式で動作します(明示的な意図が quiet モードに優先します。ADR-0020 を参照)。

モードの選択(最初に実行)

作業を開始する前に、適用するモードを決定します。

  1. --summary が指定されている場合は、モード:サマリーの生成を実行して終了します。
  2. --drain-wave が指定されている場合は、モード:Taskwarrior サイドカーの処理を実行して終了します。
  3. それ以外の場合は、以下のステップ 0 に従ってサイドカーを検出します。サイドカーが検出され、TODO.md が存在しない場合は、ユーザー向けの完了プロンプトにサイドカー処理のセマンティクスを優先して適用します。それ以外の場合は、**モード:完全同期(デフォルト)**を実行します。

モード:サマリーの生成(--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

サマリーを表示したら終了します。

モード:完全同期(デフォルト)

ステップ 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のイディオム(task bpid.any: status:any export | jq 'length'。task listは使用しません。.claude/rules/parallel-safe-queries.mdを参照)を使って、稼働中のtaskwarriorとのリンク(bpidがプロジェクトのblueprint IDと一致するタスクがあるか)も確認します。sidecarが使用されている場合、信頼できるTODOファイルがないため、TODO.mdの照合手順(ステップ4~5、8)は省略し、WOのクローズはすべてモード:Taskwarrior Sidecar Drainに振り分けます。

各status_inferredの問題は、エビデンスによってnot_startedからステータスが引き上げられた機能を示します(このガードによって、より高いステータスが引き下げられることはありません)。ステップ9のレポートでは、これらを「エビデンスから推定」の項目に記載します。標準的なマージ用jqとテストエビデンスのパターンについては、REFERENCE.mdを参照してください。

ステップ 4:不整合を検出する

次の不整合がないか確認します。

  • トラッカーではcompleteとマークされているが、TODO.mdでは未チェックの機能
  • TODO.mdではチェック済みだが、トラッカーではcompleteではない機能
  • tasks.in_progressに含まれているが、トラッカーではcompleteとされている機能
  • PRDのステータスと機能の実装ステータスが一致しない
  • not_startedとマークされているが、ステップ3bで出荷済みコードが推定された機能(ステップ5で確認)
ステップ 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"
ステップ 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 配列を持つ機能がある場合にのみ実行します。

  1. implemented_by を持つ各機能について:

    • 各 {workspace, ref} エントリに対し、 <workspace>/docs/blueprint/feature-tracker.json を読み込み、ref を検索します。

    • 子のステータスを収集します。解決できないエントリ(ファイルがない、または ref がない)がある場合は、警告を記録し、集計ではそのエントリを not_started として扱います。

    • 次のルールに基づいて、ルート機能の status を導出します。

      確認された子のステータス導出されるステータス
      解決されたエントリがすべて completecomplete
      blocked があるblocked
      in_progress がある、または complete/not_started が混在しているpartial
      すべて not_startednot_started
    • 導出した値で機能の status を上書きします。ポートフォリオ機能の implementation には触れないでください。再計算するのは status のみです。

  2. 各子の statistics ブロックを読み込み、トップレベルの workspaces サマリーを再構築します。

    "workspaces": {
      "projects/esp32-lamp": {
        "total": 14, "complete": 6, "completion_percentage": 42.9,
        "current_phase": "phase-1", "last_synced_at": "<now>"
      }
    }
    
  3. 導出したステータスを適用した後、ルートの statistics を再計算し、ポートフォリオレベルの合計に子の状態が反映されるようにします。

  4. 未解決の implemented_by エントリについて、同期レポート(ステップ 9)に警告を出力します。また、参照先のワークスペースがルートマニフェストの 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 Sidecar Drain(--drain-wave)

tasks.pending から完了した WO を 1 つ以上 tasks.completed に移し、taskwarrior の注釈(または指定したファイル/インライン文字列)から証拠を取得したうえで、実装 WO がすべてクローズ済みの FR レベルのエントリを完了にします。

ステップ 1:ウェーブリストを解析する

--drain-wave をカンマで分割します。各 WO ID について、次の優先順位で対応する証拠ソースを指定します。

  1. --evidence-files の対応する位置のエントリ(ファイルパス)。単一引用符との衝突を避けるため、jq --rawfile で読み込みます。
  2. --evidence(WO が 1 つだけのドレインの場合)。
  3. リンクされた taskwarrior タスクの最新の annotate 行(ステップ 2)。
  4. 最終手段として、AskUserQuestion でユーザーに証拠を求めます。

WO のリストと --evidence-files のリストが両方指定されていて、要素数が一致しない場合は、部分的なドレインは何もしないより悪いため、明確なメッセージを表示して実行を拒否します。

ステップ 2:taskwarrior からエビデンスを取得する

wave 内の各 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 にフォールバックします(drain の前に ユーザーがタスクを完了している場合があります)。それでも空の場合は、 ステップ 1 の次の優先ソースにフォールバックします。

各エビデンス文字列を一時ファイル(mktemp)に保存します。コミットメッセージ内の シングルクォートを jq プログラムリテラルに直接埋め込むとシェルと衝突するため、--rawfile が 標準的なエスケープ方法です:

ev_file="$(mktemp)"
printf '%s' "$EVIDENCE_STRING" > "$ev_file"
ステップ 3:pending から completed に drain する

wave 内の各 WO-NNN について、エビデンスファイル $ev_file を使い、 WO ごとに 1 回の 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

各パスが直前のパスで書き込まれたファイルを読み取るため、WO は順番に 処理します。これにより、並行書き込みが同じファイルで衝突するのを防げます。

WO ID が tasks.pending にない場合、そのエントリーについて skipped: not pending と報告し、続行します。wave 全体をエラーにしないでください。

ステップ 4:実装 WO がすべて完了したら FR のステータスを切り替える

implementing_wos 配列が drain 対象の wave と重複する各機能について、 status を再計算します。この切り替えは、ユーザーが wave ごとに繰り返す 2 つ目の手動 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:統計を再計算する

**モード:Full Sync(デフォルト)**のステップ 6 を再実行し、drain した WO と切り替えた FR が合計に反映されるようにします。その後、Full Sync の ステップ 7 に従って last_updated と current_phase を更新します。

ステップ 6:レポート

Drain Report を出力します:

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 への追加、タスクの完了、 pending 作業のキュー登録に使う jq レシピ)とサンプルのサマリーレポートについては、 REFERENCE.md を参照してください。

関連項目

  • taskwarrior-plugin:task-done — 単一の taskwarrior タスクを完了し、リンクされた トラッカーエントリーを drain します。このスキルの --drain-wave と組み合わせると、 複数の WO が一度に完了する wave 単位の drain に対応できます。
  • taskwarrior-plugin:task-coordinate — wave を開始する前に、ブロックされていない 次の N 件のタスクを提示します。これにより、ここで最終的に drain する WO が、 キューで実際にスケジュールされた内容と一致します。
  • session-plugin:session-end — セッション終了時のオーケストレーターは、調査の結果、 WO にリンクされた(bpid)taskwarrior タスクが完了済みなのに、トラッカーの tasks.pending に残っていることが分かった場合、--drain-wave パスを提供します。 そのため、誰かが手動でこの同期を実行するのを忘れて先延ばしにすることなく、 セッションの締めくくり時に drain が行われます。
  • .claude/rules/parallel-safe-queries.md — このスキルが taskwarrior を照会する際は、 task ... export | jq の慣用パターンが必須です。task list は結果が空の場合に 終了コード 1 を返し、兄弟の並列ツール呼び出しを暗黙にキャンセルします。

コメント