Repository navigation
Description
開発ループ(sprint-state.py loop sprint)から組むスプリントでも、開発版の版をリリースのプランを流す時点に決められるようにする。大方針 #2335 の柱 #2344「プランは値でなく参照を持ち、実行の直前に解決して照合する」の子の課題である。
依頼(原文)
この課題の題と本文は、起票者(課題を書いた AI)が 2026-11-01 に m26-3 のリリース後テスト(Pull Request #2351)の記録として書いた文で、利用者の指示の原文ではない。
起票時の本文(書き手: 起票者、日付: 2026-11-01):
開発ループ(
sprint-state.py loop sprint)は--devを必須の引数にしている(plugins/ndf/scripts/lib/sprint_loop_cli.py:109のrequired=True)。受け取った版をsupervise.py new sprint --version <開発版>へそのまま渡す(plugins/ndf/scripts/lib/sprint_loop.py:292-294)。
ndf 10.27.6 では、
new sprintで--versionを省くと、配布のステップを流す時点で版が決まる(#2164)。ところが開発ループから組むスプリントは必ず「明示の版」のプランになるため、この経路を選べない。並行する別のスプリントが先にその版を出すと、ループのスプリントは配布の前に止まる(#2164 の受け入れ条件 4)。そこから先は、人か conductor が版を決め直して組み直すことになる。
確かめたこと(2026-11-01 17:05 JST、導入した ndf 10.27.6):
python3 sprint-state.py loop sprint --helpを打つと、使い方の行が--mode MODE --dev DEV(必須)になっているsprint_loop.py:294は、--versionにlap["versions"]["dev"]を渡してnew sprintを組む
- m26-3(リリース記録の PR を、まとめのプランを組む時点でなく実行の時点で解決する #2230 new close: merge・手動の経路のスプリントで、リリース記録の PR をまとめの close へ渡す手段が無く、課題が --record-pr unknown で開いたまま残る #2044 開発ループの承認ゲート 2 の後のまとめが配布の記録の PR を読まない → 本番の後に記録の PR を解いてまとめを組む(#2089) #2121 スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164)のリリース後テスト(Pull Request Release: ndf v10.27.6 #2351)
- スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 の設計の「未確認」に「
sprint-state.py loop sprintの--dev… 範囲外の課題として起こす」とあるが、まだ起票されていない(承認資料issues/approval-ndf-v10.27.6.mdの 34 行目)
#2164 の要求の対象範囲は
supervise.py new sprint/new closeが組むプランであり、開発ループの引数は含まない。開発ループからは明示の版のプランとして受け入れ条件 4・10 が当たるため、退行はしない。根拠: Value 4(手当てを雛形へ入れる)・Vision(人が手を止めるのは承認の 2 回に寄る)(MVV 版 3)。
開発ループで回すスプリントだけが、#2164 で無くした「並行するスプリントが先に版を出すとプランを作り直す」手当てを残す。ループは人を介さずに周回を続けることが目的のため、版がぶつかるたびに周回が止まり、人へ戻る。
由来: PR #2351
柱への結び付け(書き手: 起票者、日付: 2026-11-01。課題のコメント):
大方針 #2335 の柱 #2344(プランは参照を持ち、実行の直前に照合する)の子として扱います(スプリント lroot-2 の棚卸し)。
範囲の指示(書き手: 利用者、日付: 2026-11-05。#2344 の設計承認ゲート の答え。#2344 の本文から引用した):
範囲を、起きた不具合に根拠のあるものに絞る: 版数・リリース記録の PR の直前の解決(#2164)・実行条件を先に評価(#2349)・流し直しの判定(#2349)・開発ループの版(#2354)。
この要求の整理の指示(書き手: AI の起動指示、日付: 2026-11-06):
人へ問わずに進め、決められない点は前提か未決として課題の本文へ書く。
解釈: 開発ループの周回で、版の指定を不要にする。--dev を渡さなければ new sprint に --version を渡さず、#2164 の経路(流す時点に次に空いている版を決める)へ載せる。あわせて、版を渡さなくても周回の記録に出した版が残る状態を保つ。今の --dev を渡す使い方は残す。
起票者の推定
| # | 条件 | 推した出所 | この要求での扱い |
|---|---|---|---|
| S1 | ループの --dev を省けるようにし、省いたら new sprint に --version を渡さない形が望ましい |
#2164 の受け入れ条件 1・3 と、承認資料 issues/approval-ndf-v10.27.6.md の 34 行目 |
受け入れ条件 1・2 |
| S2 | 並行するスプリントとループのスプリントが版でぶつかる頻度は測っていない | 起票者の推測 | 前提 5(測らずに直す) |
| S3 | 版がぶつかるたびに周回が止まり、人へ戻る | 本文の「直さないと何が起きるか」 | 開発版の版は受け入れ条件 3・4 で解消する。本番の版は前提 3 のとおり止まる側に残す |
| S4 | 手当ての位置づけとして、この課題を柱 #2344 の子に置く | 課題のコメント(2026-11-01) | 前提 1 |
目的
- 開発ループの周回が、並行するスプリントの開発版のデプロイで止まらず、プランを作り直さずに次に空いている版で開発版を出す状態にする
- conductor が周回ごとに版を決める手順を無くし、判断の要らない手順をスクリプトへ寄せる
今の開発ループは版を必須で受けるため、ループのスプリントだけが #2164 の経路を選べない。
前提
- 前提 1: この課題は プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 の実装を待たず、スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 で入った版の差し込みの上で完結する。プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 の受け入れ条件 8(
--devを省いて起動でき、省いたらプランが版を参照で持ち、渡せば明示の版になる)は、この課題の受け入れ条件 1・2・5 で満たす形にそろえる。後から プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 が差し込みを参照の部品へ寄せても、開発ループの側は「--versionを渡さない」だけなので変更が要らない。確認: origin/develop(ac5389bae)にplugins/ndf/scripts/lib/refs.pyは無く(lsで確認)、git grep -n 2344 -- 'plugins/ndf/scripts/**/*.py'は 0 件で、プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 は未完了(OPEN)である - 前提 2:
--devは引数として残す(任意にする)。特定の版で出す必要があるときの手段である。手順書の既定の打ち方は--devを渡さない形にする - 前提 3: 本番の版が既出のときに自動で次へ移らない スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 の規則(同じ設計の不変条件 I4・I5)は変えない。リリース承認ゲート で判定した承認資料の版と、出す版を食い違わせないためである。したがって本番のプランまで進んだ後に別のスプリントが同じ版を本番へ出した場合は、今と同じく止まって人へ戻る
- 前提 4: 版を決める規則(
decide_dev・taken・bumpの止まり方)は変えない。開発ループがどの経路を選ぶかだけが変わるため、必ず人の承認が要る操作 P1(リリース対象の取得元・版の規則の変更)に当たらない - 前提 5: 版がぶつかる頻度は測らない。この変更は手順を減らすもので、頻度によらず周回の止まる経路を 1 つ無くす
- 前提 6: 適用範囲は スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 と同じく
.ndf/supervise.jsonのrelease.formがpackage-pluginで、delivery.needs_versionが真の経路である
対象範囲
含む:
sprint-state.py loop sprintの--devを任意にし、省いたらnew sprintへ--versionを渡さないこと--devを省いて--prodだけを渡した呼び方の扱い- 周回の記録(
loop.json・laps.md)の版を、版の記録から埋めること - 開発ループの案内の文(
loop selectと止まった後のnext)と手順書references/loop.mdの打ち方 -- --level <上げ幅>で上げ幅を渡せることの確認
含まない:
- 版を決める規則そのものの変更(前提 4)
- 本番の版が既出のときの自動の移動(前提 3)
- 差し込みを参照の部品へ寄せること(プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 の範囲)
- 並行するスプリントの版の取り合いを排他にすること(プランは値でなく参照を持ち、実行の直前に解決して照合する #2344 の設計が「測っていない」としている項目)
new sprint/new closeを直接打つ経路の変更(スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 で完了)- 確定仕様
docs/specifications/ndf-release-version-at-run-time.mdの「運用」の 289 行目の書き換え(確定仕様化の工程で行う)
ドメインイベント
| # | イベント | 引き金 | 失敗したとき | 順序の前提 |
|---|---|---|---|---|
| E1 | conductor が --dev なしで loop sprint を打った |
loop select が課題を選んだ |
--prod だけを渡した → 断る(受け入れ条件 7)。進行中の周回が無い → 今と同じく断る |
選定が済んでいる |
| E2 | 開発ループが版を持たないスプリントのプランを組んだ | E1 | init・new sprint・new close のどれかが断った → 今と同じく refused で止まり、next をやり直す(受け入れ条件 11) |
E1 |
| E3 | 別のスプリントが同じ系列の版を先に出した | 並行するスプリントのリリース | 開発ループの中では失敗しない。E4 が扱う | E2 の後の任意の時点 |
| E4 | キューが開発版のプランの直前に版を決め、版の記録を書いた | 開発版のステージを流す直前 | origin を読めない → 流さず unreadable で止まる(#2164 のまま) |
検査のステージが終わっている |
| E5 | キューが版を決め直した | 流し直しで記録の版がもう出ていて、自分のリリースがマージされていない | 手順の途中で落ちる → 流し直しで同じ結果へ戻る(#2164 のまま) | E4 |
| E6 | 開発版を出した | リリースのステップ | 今のリリースの失敗の扱いのまま | E4 |
| E7 | 本番の版を開発版の記録から決めた、またはレーンのリリースの依頼の答えで本番の版を受け取った | 本番のステージ、またはリリースの依頼の答え | 既出 → 止まって人へ戻る(前提 3) | E6 |
| E8 | 周回を締め、出した版を周回の記録へ書いた | loop lap か loop finish |
版の記録が無い・読めない → 版の欄を空のまま締める(受け入れ条件 10) | E2 |
用語
| 用語 | 意味 |
|---|---|
| 開発ループ | スプリントを 1 つ終えるたびに次のスプリントを選んで続けて始める進め方 |
| 周回 | 開発ループの 1 回分 |
| ループの記録 | 周回ごとの選定・判定・版・費用を持つ記録(.ndf/loop/<名>/loop.json。laps.md はそこから描画する) |
| 版の差し込み | プランの版を書く箇所に置き、キューが流す直前に埋める語({release_version}・{release_base}) |
| 版の記録 | プランの状態ディレクトリの version.json。キューが決めた版を持つ |
| 版の決め直し | 流し直しで記録の開発版がもう出ていたときに、次に空いている版へ取り直すこと |
| 明示の版 | 呼ぶ側が渡した版。プランの「版」の欄の 明示 に入る |
受け入れ条件
- 1.
loop sprint <名> --mode <モード>は--devなしで終了コード 0 で返る。組んだ開発版のプランの「版」の欄の明示は空(null)で、プランのファイルとsprint.jsonにX.Y.Zの形の版数が無い - 2.
--devなしのとき、周回の記録のsprint_commandに--versionが無い
前提の確認:sprint-state.py initとsupervise.py new sprint --pace auto(--versionなし)を打つと 0 で返り、7-release.jsonの「版」の欄の明示はNone、版数の形は 0 件(2026-11-06、この課題の worktree で実行) - 3.
--devなしで組んだ後、origin のベースブランチと本番へ10.27.6とタグを足してから開発版のプランの差し込みを流すと、プランを作り直さずに10.27.7-dev.1で埋まり、版の記録のhowはdecidedである(一時の git リポジトリで確かめる) - 4.
--devなしで組み、版の記録を書いた後に別のスプリントがその版を出し、自分のリリースがマージされていない状態で流し直すと、周回を止めずに版を決め直す。historyに 1 件入る - 5.
--dev <版>を渡すと、今と同じくnew sprint --version <版>を打ち、開発版のプランの明示がその版になる。その版が既出なら、今と同じく流さずversion.causeがtakenになる(退行しない)
前提の確認:supervise.py new sprint --pace auto --version 10.28.0-dev.1の7-release.jsonの明示が10.28.0-dev.1(2026-11-06)。既出の扱いは スプリントのプランが作った時点の版数を配布と本番のプランへ書き込み、並行する別のスプリントがその版を先に出すとプランを作り直すまで止まる #2164 の不変条件 I5 - 6.
--dev <版>を渡したとき、周回の記録のversionsは今と同じく開発版とその接尾辞を外した本番の版(--prodがあればその版)を持つ(退行しない) - 7.
--devなしで--prod <版>を渡すと、終了コード 1 で断り、理由に「--prodは--devと一緒に渡す」旨が出る。状態ファイルを作らず、new sprintを打たず、ループの記録を変えない - 8.
loop sprint <名> --mode <モード> -- --level minorで組んだ開発版のプランの上げ幅はminorである
前提の確認:supervise.py new sprint --pace auto --level minorの7-release.jsonの上げ幅がminor(2026-11-06) - 9.
--devなしの周回で開発版のプランが版の記録を書いていれば、周回を締めた後のversions.devは版の記録の版で、laps.mdの版の列に出る。版を決め直した周回は決め直した後の版が載る - 10.
--devなしの周回で版の記録が無い、または読めないとき、周回は今の結果のまま締まり、versions.devは空で、laps.mdの版の列は空である(周回の締めを止めない) - 11.
loop selectのnextと、refusedで止まった後のnextが示す 1 行は--devを求めず、その行のモードを埋めて打つと受け入れ条件 1 のとおり組める - 12.
sprint-state.py loop sprint --helpの使い方の行で--devが任意([--dev DEV])になっている
前提の確認: 今は--devなしで打つと終了コード 2 でthe following arguments are required: --dev(2026-11-06) - 13.
references/loop.mdの手順 2・3 の打ち方は--devを渡さない形で、conductor が版を決める手順が無い。書いたコマンドはそのまま打って通ることを、書く前に実行して確かめる - 14.
pytest plugins/ndf/scripts/tests/test_sprint_loop.pyが通る。--devを渡す既存のテストの期待値は変えない(nextの文面を確かめる行を除く)
前提の確認: 変更前にuv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests/test_sprint_loop.py -q -n 4→ 184 passed(2026-11-06)
非機能の条件
| 大項目 | 条件 |
|---|---|
| 運用・保守性 | 周回の記録の版の出所は、スプリント状態の版の欄と版の記録の 2 つに限る。周回の記録だけを読めば、周回ごとの出した版が分かる状態を保つ |
| 移行性 | 進行中の周回の記録と、--dev を渡して組んだプランはそのまま流れる。記録の形(versions の鍵)を変えない |
影響
| 対象 | 影響 |
|---|---|
| 公開インタフェース | 変わる。loop sprint の --dev が必須から任意になる。今の呼び方はそのまま通るため互換を保つ。--dev なしの --prod は今も --dev が無いと打てないため、断っても今の呼び方を壊さない |
| データ | スキーマの変更なし。--dev なしの周回では、周回の記録の versions の値が締めるまで空になる |
| 既存の振る舞い | conductor が周回ごとに版を決める手順が無くなる。--dev を渡す経路は変わらない |
| 呼び出し元 | Factory は loop sprint の引数を組まない。確認: grep -rn '\-\-dev' factory と grep -rln 'loop sprint' factory(node_modules を除く)は 0 件。sprint_loop.py の外で周回の versions を読むのは sprint_loop_gate.py・sprint_loop_gate2.py・sprint_loop_record.py の 3 ファイルで、いずれも空の値を許す形である |
検証手段
| 項目 | 手段 |
|---|---|
| 起動 | python3 plugins/ndf/scripts/sprint-state.py loop sprint --help |
| テスト | uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests/test_sprint_loop.py plugins/ndf/scripts/tests/test_release_version.py -q -n 4 |
| 静的解析・型検査 | リポジトリの既存の CI の検査 |
| 手動確認 | 開発版を入れた環境で、開発ループの 1 周を --dev なしで回し、周回の記録の版の列に出した版が載ることを見る(リリース後テスト) |
前提とする取り決め
| 項目 | 参照先 / 決めたこと |
|---|---|
| プロジェクト構造 | 開発ループは plugins/ndf/scripts/lib/sprint_loop*.py、版の判定は lib/release_version.py に置く。既定で働く経路のため experimental/ に置かない(AGENTS.md の「安定版と実験版」)。factory/ を参照しない |
| コーディング規約 | AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストを書かない |
| テスト戦略 | 引数と組み立ては test_sprint_loop.py の単体テスト、版の決定と決め直しは一時の git リポジトリを使う結合テストで確かめる(test_release_version.py の形に合わせる) |
境界
| 区分 | 内容 |
|---|---|
| 常に行う | 既存テストの実行、--dev を渡す経路の退行の確認 |
| 確認してから行う | 公開インタフェースの変更(--dev の任意化)。設計承認ゲートとリリース承認ゲート で人が見る |
| 行わない | 版の規則の変更、--dev の削除、#2344 の参照の部品の先取り |
未決
| 項目 | 誰が決めるか | 期限 |
|---|---|---|
テンプレートで配らない形(前提 6 の外)のプロジェクトで --dev を省いたときの組み立て。new sprint のテンプレートを使わない経路は版を使わない見込みだが、未確認である |
design の工程で実行して確かめる |
設計承認ゲート まで |
周回の記録へ版を書く時点(周回を締めるときだけか、laps.md を途中で描くときも読むか)と、本番の版の読み先 |
design の工程 |
設計承認ゲート まで |
進行
モード: — / 進め方: auto
- 要求と受け入れ条件 — 2026-11-06 11:07
- 作業場所の用意 — 2026-11-06 22:36
- 設計 — 2026-11-06 11:16
- 素材の収集と出典の確定
- ドキュメント再構成 — 2026-11-06 11:25
- ドキュメントレビュー
- 計画 — 2026-11-06 22:36
- 実装 — 2026-11-06 22:36
- 構造改善 — 2026-11-06 23:43
- 実装レビュー — 2026-11-07 00:48
- 完了判定 — 2026-11-06 22:51
- Pull Request — 2026-11-06 23:13
- 確定仕様化
- 後片付け
- デプロイ — 2026-11-07 01:09
- 体裁レビュー
- リリース後テスト
- 振り返り
- 棚卸し
人の判断待ち(開発ループ lroot4)
- 判定: unknown(承認ゲート 1)
- 理由: Mission・Vision: 開発版のぶつかりで周回が止まらなくなり、人が版を決め直す手間が減るため、「人の判断が要る所だけで止まる」方向に沿う/Value 5・6・7: 版の決定はキューの既存の処理に任せ、版の記録の読み取りは持ち主の層に置き、リリースの形ごとの分岐も足さないため、反する点は読み取れない/Value 2(決められないときは人へ戻す): 設計は、要求の「版の出所は 2 つに限る」とレーンのリリースの依頼の答えという 3 つ目の出所の食い違いを残し、条件の文言を直すかは設計承認ゲートで人が見ると明記している。承認を省くと、人へ委ねたこの判断が抜けるため、AI だけでは決められない/Value 1(確かめていないものを済んだと記録しない): 開発版のデプロイに失敗した周回でも、出していない開発版が周回の記録に載る。受け入れ条件 9 に従った動きとして未確認の欄に明記されているが、記録を「出した版」として読む非機能の条件との緊張があり、許容できるかは材料から決められない/P1・C1〜C8: 版の決定の規則は変えず、変更は文書 2 件で、実装の予定も
plugins/ndf/のスクリプト・テスト・手順書に限られる。.ndf/やCLAUDE.mdは書き換えないため、必ず人の承認が要る操作には当たらない - 根拠の項目: Mission, Vision, Value 1, Value 2, Value 5, Value 6, Value 7, P1, C7
- 設計 Pull Request: 開発ループ: 周回ごとに版を決めずにスプリントを組み、並行するリリースがあっても次に空いている開発版で出す(#2354) #2679
- 答え: approved
- 答え方:
python3 /work/ai-plugins/plugins/ndf/scripts/sprint-state.py loop answer lroot4 2354 --approved|--rejected|--revise --note <指摘ファイル>
設計承認ゲート での利用者の指摘(直して出し直す)
設計 PR 2679(#2354)を出し直す前に、次の 3 点を直す。
- 決定 2(設計 105 行)の本番のプランの完了の判定を直す。人がリリース承認ゲート を承認して本番を出した周回でも、スプリント状態のプランの行の結果は前の done から作られるため元の値のまま残り、続きの
run <本番のプラン> --from <ステップ>は done を書かない。今の判定だと本番の版が周回の記録に載らない。完了の確かめ方を、続きの実行も書く本番のプランの状態ディレクトリの report.md の「結果」へ変えるか、gate2_pipeline の続きの結果を done へ載せると決める。235 行の契約・図の H・I4 も合わせ、「承認して本番を出した周回に本番の版が載る」行をテスト設計へ足す。 - glossary-check の失敗を直す。設計 105 行の廃止語を「承認ゲート」系の語へ置き換える。
- requirements-check の exit 2(issues/issue-2354-requirements.md を読めない)の原因を確かめて再実行し、PR 本文のテストの表を結果に直す。止まった最終スイープは再レビューで補う。
設計の承認ゲート 1 での利用者の答え(2026-11-07)
- 本番の版の出所は要求の文言を実態に合わせて 3 つ(レーンの配布の依頼の答えを含む)に直す
- 開発版のデプロイに失敗した周回に、出していない開発版が載ることは「出す予定の版」として許容する
Activity
takemi-ohama commentedon Nov 1, 2026
大方針 #2335 の柱 #2344(プランは参照を持ち、実行の直前に照合する)の子として扱います(スプリント lroot-2 の棚卸し)。
Docs: 本番の完了の確かめを report.md の結果へ変え、origin の修正を取り込む(#2354)
Docs: #2354 の設計と要求の語を develop の用語集へそろえる
Merge pull request #2679 from devbasex/design/issue-2354
Merge pull request #2713 from devbasex/feat/issue-2354-lroot4-6
Merge: develop を取り込み、#2354(版を流す直前に決める)と #2623・#2510 を合わせる