develop/tasks.json を1サイクルぶん前に進める。フィールドの定義・difficulty の意味・
evidence の書き方・アーカイブのトリガーは task-workflow スキルの WORKFLOW.md
(以下「正典」)にあるのでここでは繰り返さない。このスキルは1タスク分を実行して終わる。
全件 done になるまで繰り返したい場合は /loop /next-task として使う(/loop 側が
続行/停止を判断する)。
このプロジェクトの設定(CLAUDE.md の「## タスク運用」節)
!sed -n '/^## タスク運用/,/^## /p' CLAUDE.md 2>/dev/null | grep . || echo '(「## タスク運用」節が無い。CLAUDE.md の他の節に書かれた検証コマンドを探す。無ければ /setup-tasks で節を用意する)'
以下で検証コマンド・整形コマンドと書いたところは、この節の値に読み替える。
値が なし なら、そのコマンドは走らせず、タスク本文の「## 完了条件」だけで受け入れを
判定して、その旨を報告に書く。節が無い場合は「なし」と決めつけない——まだ節に移して
いないだけで、CLAUDE.md の別の節に「変更後は必ず〜を通す」と書いてあることが多い。
それも無いときだけ、検証コマンド無しで進める。アーカイブの置き場
(docs/history/)と予算は規約で固定(正典「ファイル配置と CLAUDE.md」)。
develop/tasks.json が無いプロジェクトなら、タスク運用を始めていない旨を報告して終了する
(勝手にファイルを作らない)。
タスク本文を読み込まない
1タスクの task 本文は数KBある。1件を選ぶために全件の本文を読まない。選ぶのに要る値
(status・dependencies・difficulty・loopable・summary)は全部 status.py の TSV に
出るので、本文を読むのは選んだ1件だけにする。develop/progress.md も同じで、このスキルが
するのは「完了したこと」の先頭への追記だけなので、全文を読まない(判定は status.py の
progress 行が出す)。
/list-tasks と同じ方針。tasks.json が数万文字まで育つ運用なので、ここを守るかどうかで
1サイクルのコンテキスト消費が一桁変わる。
スクリプトが動かないとき
status.py / archive.py は python3 を使う。python3 が無い・エラーで落ちる環境では、
tasks.json を全文読んで代用しない。 節約の仕組みが死んでいることに気づけないまま、
毎サイクル数万文字を読む状態になるため。
止まる理由は2つあり、報告先が違う。 混同すると、直すべき場所と違うところを指してしまう:
| 出力 | 何が起きたか | すること |
|---|---|---|
INVALID\t<path>\t<理由> |
tasks.json が読めない(JSONが壊れている、配列ではない) |
データの不備。理由をそのまま報告して終了する。直しに行かない(運用中のデータなので、中身を確かめずに書き換えると進行中のタスクを失う) |
MISSING・EMPTY・INVALID・TSV のいずれでもない出力 |
python3 が無い、スクリプトが traceback で落ちた |
環境の故障。python3 が使えない旨とエラー出力を報告して終了する |
どちらも /loop 側は「続行不要」の合図として扱う。なお TSV の末尾に出る missing_field 行は
止まる理由にはならない(フィールドが欠けたタスクを ? で出したという報告で、一覧としては
成立している)。該当があれば完了報告に添える。
手順
見渡す: 一覧と判定はスクリプトが出す。
develop/tasks.jsonを Read ツールで開いたりcatしたりしない(理由は下の「タスク本文を読み込まない」)。python3 ${CLAUDE_SKILL_DIR}/../task-workflow/scripts/status.py develop/tasks.jsonMISSINGならタスク運用を始めていない旨を報告して終了する。EMPTYなら登録されている タスクは0件。INVALIDならtasks.jsonが読めない(上の「スクリプトが動かないとき」)。 TSVの読み方は/list-tasksと同じ(列はid / status / difficulty / loopable / dependencies / 着手可否 / passes / summary)。末尾の
archive行(tasks.jsonの判定)かprogress行(progress.mdの判定)がYESなら、着手前にアーカイブする(正典「いつ移すか(トリガー)」)。転記は判断を 含まないので手で書き写さず、スクリプトに任せる:python3 ${CLAUDE_SKILL_DIR}/../task-workflow/scripts/archive.py develop/tasks.json出力の
MOVED行に、移したタスクIDとファイルサイズの前後が出る。完了報告にそのまま載せる。あわせて
develop/direction.mdを節ごとに見る(正典「指示メモ」の2節)。節見出しが 1つも無い(この変更より前に作られた)ファイルは、全体を## ユーザーからとみなす (後方互換):# ## ユーザーから の行数 awk '/^## ユーザーから/{f=1;next} /^## /{f=0} f' develop/direction.md | grep -v '^\s*$' | wc -l # 節見出しが無ければ代わりにこちらの行数を「## ユーザーから」として扱う grep -v '^#' develop/direction.md | grep -v '^\s*$' | wc -l # ## エージェントのドラフト の行数 awk '/^## エージェントのドラフト/{f=1;next} /^## /{f=0} f' develop/direction.md | grep -v '^\s*$' | wc -l## ユーザーからに中身があれば未タスク化の指示が残っている。READYなタスクが あるならそちらを止めず、READYが0件のときだけ手順2でその場でタスク化する (正典「指示メモ」)。## エージェントのドラフトの行数は「未承認のドラフトが溜まっている」という状態であって、/plan-tasksを急かす理由にはしない(正典「指示メモ」の承認ゲート)。それぞれの行数を 完了報告に添える(手順2・「完了報告のフォーマット」で使う)。選ぶ: まず手順1のTSVに
statusがdoingの行が無いか見る。あれば前回セッションの 異常終了で着手途中のまま残ったタスクなので、READYを選ぶより先にそちらを扱う。doingは自動では拾い直さない(status.pyの着手可否列もdoingにはREADYを 出さない)。作業ツリーに何が残っているか分からない状態でサブエージェントに委譲すると、 「本文だけで作業が完結する」という前提(正典「difficulty に応じたモデルの切り替え方」)が 崩れるため。該当タスクIDを添えて「T-xxxがdoingのまま残っている。作業ツリーを 確認してから再開するか判断してほしい」と報告して終了する(他にREADYがあっても、 まずここで止まる。/loop側はこれを「続行不要」の合図として扱う)。doingの行が無ければ、TSVで着手可否がREADYの行から1件選ぶ(status: "todo"かつ 依存が全て解決済み。tasks.jsonに存在しない依存=アーカイブ済み=完了扱いは スクリプトが織り込み済み)。READYが無ければ(全件 done、または残りが全てBLOCKED:)、 手順1で見た## ユーザーからの中身の有無で分かれる(## エージェントの ドラフトだけに中身がある場合は「中身が無い」側で扱う。正典「指示メモ」):## ユーザーからに中身がある → ここで止めず、その場でタスク化して続ける。plan-tasksスキルを読み、その手順2〜8(確かめる・分解する・書く・登録する・ 指示メモを移す・コミット)をファイル入口(## ユーザーから)の分だけに対して 実行する。手順の正典は/plan-tasksなのでここには書き写さない。/loopから 回っている最中でも触ってよいのはこの節だけで、会話入口と## エージェントのドラフトには従来どおり触らない(正典「指示メモ」)。タスク化のコミットはまだブランチを切る前 (デフォルトブランチ)で済ませ、doneのコミットとは分ける(1タスク=1コミット。 正典「コミットメッセージ」)。済んだら手順1のTSVを取り直し、着手可否がREADYの 行から1件選んで手順3へ進み、そのまま1サイクルを終える(選び方はこの手順の上と同じで、/loopから回っているときはloopable: "N"を選ばないところまで変わらない)。 タスク化してもREADYが1件も生まれなければ(登録したものが全てloopable: "N"、 依存で全てBLOCKED:など)、登録したタスクIDとREADYが無い理由を添えて報告して 終了する## ユーザーからに中身が無い → 「進められるタスクが無い」とだけ報告して終了する (## エージェントのドラフトに未承認の行があれば、件数だけ添える)
報告して終了したときは、どちらも
/loop側はこれを「続行不要」の合図として扱う。選んだら、その1件の本文だけを読む:
python3 -c "import json,sys; print([t for t in json.load(open('develop/tasks.json')) if t['id']==sys.argv[1]][0]['task'])" T-XXX/loopから回されているときはloopableが"N"のタスクを選ばない (正典「loopable」。フィールドが無いタスクは"Y"扱い)。残りが"N"だけになったら 「ユーザーの判断が必要なタスクのみが残っている」と、そのタスクIDを添えて報告して終了する (/loop側はこれを「続行不要」の合図として扱う)。ユーザーが直接/next-taskを 呼んだときは"N"も選んでよい。その場合は着手前に、ユーザーの判断が要る点を先に確認する。ブランチ: 既定は選んだタスクの
feature/T-<タスクID>ブランチを切って作業する (例:T-008を選んだらgit switch -c feature/T-008。デフォルトブランチから分岐する)。 プロジェクトのCLAUDE.md「## タスク運用」節の- ブランチ:行がこの既定と違う運用を 書いていれば、そちらに従う(正典「ファイル配置と CLAUDE.md」)。doingにする: 選んだタスクのstatusを"todo"から"doing"に書き換える。develop/tasks.jsonの対象タスク1件だけを編集し、passes・evidenceなど他のフィールドは 触らない。この変更はコミットしない(作業ツリー上にだけ置く。理由と、doneへ変わる タイミングは正典「tasks.json のフィールド」のstatusの行)。実行: Agentツールで、選んだタスクの
difficultyと同じモデルを指定した サブエージェントに委譲する(正典「difficulty に応じたモデルの切り替え方」):haiku/sonnet/opusのいずれでも委譲する。メインセッションが今どのモデルで 動いているかは判断材料にしない(メインと一致していても委譲する。理由は正典 「なぜ一致していても委譲するのか」)tasks.jsonのtask本文だけで作業が完結するよう、対象ファイル・完了条件・ 検証コマンドを通すことを明記して渡す(サブエージェントはまっさらな文脈で起動する)task本文を prompt に貼り付けない。 タスクIDと、手順2で使ったのと同じ読み取り コマンドを渡してサブエージェント側に読ませる(貼ると本文がメインの出力トークンになる。 正典「difficulty に応じたモデルの切り替え方」)develop/tasks.jsonはコミットしないことを明記して渡す。 手順4で当該タスクのstatusをdoingに書き換えた直後の状態で委譲が始まるため、サブエージェントがgit add -Aのような一括ステージングを行うとdoingのままコミットされてしまう (記録は手順7でメイン側が行う)- ユーザーへの確認が必要な判断・会話中の文脈に依存する判断は委譲しない。これは
モデル選択とは別の軸の話で、登録時の見立ては
loopableに入っている。着手して 初めて分かった場合はloopableを"N"に直し、委譲せずユーザーに預けて次のタスクへ進む - 着手後に想定より判断が重いと分かったら、
difficultyを上げてから改めて進める
受け入れ: 委譲した場合は完了報告をそのまま信用せず、自分で差分(
git diff)を確認し、 整形コマンドがあれば実行してから検証コマンドを実行して通ることを確かめる。 検証コマンドが「なし」なら、タスク本文の完了条件を1つずつ目視で確かめ、報告に 「検証コマンド未設定」と書く。方針からズレた実装(例: コメントの動機がすり替わっている、 命名が既存規約と衝突する)があればその場で直してから次に進む。記録してコミット:
develop/tasks.jsonの対象タスクのstatusを"doing"から"done"に書き換え、passes/evidenceも更新する(evidence は3行以内、後から検証できる 形で。正典「良いevidenceの書き方」)。develop/progress.mdの「完了したこと」に、 そのタスクの小節を1つ、節の先頭に足す(### YYYY-MM-DD 何をしたか(T-xxx)の形で、 中身は1〜2文)。既にある小節に混ぜず、上に積む——並びが「新しい順」であることに アーカイブが依存していて、下に足すとスクリプトがERRORを返して止まる (正典「progress.md の構成」)。1タスク=1コミットとし、件名の先頭にタスクIDを置く(正典「コミットメッセージ」)。 手順4の
doingへの書き換えはコミットしていないので、ここでの差分はtodo→doneの1回ぶんになる。コミットメッセージの末尾は現在のセッションの attribution 指示(Co-Authored-By 等)に従う。マージ: 作業ブランチをデフォルトブランチへふつうの
git mergeで取り込む (git switch main && git merge feature/T-XXX)。main がブランチの分岐後に進んで いなければ fast-forward で取り込まれ(コミットは増えない)、進んでいればマージコミットが できる。どちらでもよい。成功したら作業ブランチを削除する(git branch -d feature/T-XXX)。コンフリクトが起きたら、黙って解消しようとせず、コンフリクトしたファイルを報告して ユーザーに預けて終了する(
resolving-merge-conflictsスキルで解消できる。/loopは これを「続行不要」の合図として扱う)。作業ブランチは削除せずに残す。検証コマンドを通す位置: fast-forward で済んだ場合は再実行しない(手順6で通した結果の まま main の内容が作業ブランチの到達点と同一になるため)。マージコミットができた場合は、 main で検証コマンドをもう一度通す(両側の変更が初めて同居する状態になるため。正典 「ファイル配置と CLAUDE.md」の「ブランチ運用」)。これが落ちたらmain を壊れたまま 放置せず、マージ直前の
HEADへgit reset --hardして main を元に戻す(作業ブランチには 同じコミットが残っているので作業は失われない)。reset の前にgit status --shortを見て、 自分が作ったのではない未コミットの変更が無いことを確かめる(あれば reset せず報告だけする)。検証コマンドの出力と main を巻き戻した旨を 報告してユーザーに預けて終了する(/loopはこれを「続行不要」の合図として扱う)。作業 ブランチは削除しない。push はしない: 外部への反映は明示的に頼まれたときだけ行う。このスキルはローカルのマージまでで止める。
完了報告のフォーマット
最後に必ず次を1行ずつ示す(/loop が続行判断に使う):
- 今回 done にしたタスクID
- 検証コマンドの結果(ファイル数・テスト件数。「なし」なら、完了条件を目視で確かめたこと)
- 残りの
todo件数(0なら「全タスク完了」と明言する)。うちloopable: "N"が 何件かも添える(/loopでは進まないので、ユーザーが自分で呼ぶ必要があるため) - このサイクルで手順2の分岐に入ってタスク化したなら、登録したタスクIDと、そのコミットが
doneのコミットとは別であること - 未タスク化の指示(
develop/direction.md)の有無。節ごとの行数を分けて書く (## ユーザーから/## エージェントのドラフト)。タスク化した場合は移したあとの行数