Skip to content

開発ループのスプリントが版を流す時点に決められず、並行するスプリントと版がぶつかると止まる #2354

Open

Description

@takemi-ohama

開発ループ(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 を組む

#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 の経路を選べない。

前提

対象範囲

含む:

  • sprint-state.py loop sprint の --dev を任意にし、省いたら new sprint へ --version を渡さないこと
  • --dev を省いて --prod だけを渡した呼び方の扱い
  • 周回の記録(loop.json・laps.md)の版を、版の記録から埋めること
  • 開発ループの案内の文(loop select と止まった後の next)と手順書 references/loop.md の打ち方
  • -- --level <上げ幅> で上げ幅を渡せることの確認

含まない:

ドメインイベント

# イベント 引き金 失敗したとき 順序の前提
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 点を直す。

  1. 決定 2(設計 105 行)の本番のプランの完了の判定を直す。人がリリース承認ゲート を承認して本番を出した周回でも、スプリント状態のプランの行の結果は前の done から作られるため元の値のまま残り、続きの run <本番のプラン> --from <ステップ> は done を書かない。今の判定だと本番の版が周回の記録に載らない。完了の確かめ方を、続きの実行も書く本番のプランの状態ディレクトリの report.md の「結果」へ変えるか、gate2_pipeline の続きの結果を done へ載せると決める。235 行の契約・図の H・I4 も合わせ、「承認して本番を出した周回に本番の版が載る」行をテスト設計へ足す。
  2. glossary-check の失敗を直す。設計 105 行の廃止語を「承認ゲート」系の語へ置き換える。
  3. requirements-check の exit 2(issues/issue-2354-requirements.md を読めない)の原因を確かめて再実行し、PR 本文のテストの表を結果に直す。止まった最終スイープは再レビューで補う。

設計の承認ゲート 1 での利用者の答え(2026-11-07)

  • 本番の版の出所は要求の文言を実態に合わせて 3 つ(レーンの配布の依頼の答えを含む)に直す
  • 開発版のデプロイに失敗した周回に、出していない開発版が載ることは「出す予定の版」として許容する

Activity

  1. takemi-ohama commented on Nov 1, 2026

    @takemi-ohama
    ContributorAuthor

    大方針 #2335 の柱 #2344(プランは参照を持ち、実行の直前に照合する)の子として扱います(スプリント lroot-2 の棚卸し)。

  2. added 5 commits that reference this issue on Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions