Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4133880
Feat: まとめの記録の PR を流す時点に {queue_record} で探す(#2230)
takemi-ohama Nov 1, 2026
00de444
Docs: まとめの --record-pr の説明を {queue_record} に直す(#2230)
takemi-ohama Nov 1, 2026
75ee6f5
Docs: まとめが {queue_record} を組む変更を確定仕様へ反映する(#2230)
takemi-ohama Nov 1, 2026
534eb91
Merge pull request #2333 from devbasex/feat/issue-2230-m26-3
takemi-ohama Nov 1, 2026
2673edc
Feat: 配布の bump が版を戻す呼び方と既にタグのある版を止める(#2164)
takemi-ohama Nov 1, 2026
e440741
Feat: 版を渡さずに作ったスプリントの配布のプランが版の差し込みを持つ(#2164)
takemi-ohama Nov 1, 2026
48485f7
Feat: キューが配布のプランの版を流す時点に決め、版の記録に残す(#2164)
takemi-ohama Nov 1, 2026
54416c7
Docs: スプリントの配布の版が流す時点に決まることと止まり方を書く(#2164)
takemi-ohama Nov 1, 2026
8b8c50b
Fix: 版の判定がプラグインの置き方を仮定せず、ベースブランチの木から plugin.json を探す(#2164)
takemi-ohama Nov 1, 2026
626b582
Update: 宣言の整形を当てる(lint-fix)
takemi-ohama Nov 1, 2026
766a923
Fix: 構造の検査に合わせ、bump の版の判定を release_version へ移し、同じ名前の補助関数を改める(#2164)
takemi-ohama Nov 1, 2026
785de50
Docs: 本番のプランの版を省いたときに開発版の版の記録から埋まることを確定仕様へ反映する(#2164)
takemi-ohama Nov 1, 2026
f9cb799
Merge pull request #2345 from devbasex/feat/issue-2164-m26-3
takemi-ohama Nov 1, 2026
0b5fafc
Refactor: extract_method — plugins/ndf/scripts/lib/sprint_loop.py#cmd…
takemi-ohama Nov 1, 2026
da67d1f
Refactor: extract_method — plugins/ndf/scripts/sprint_close_lib/recor…
takemi-ohama Nov 1, 2026
658e5e3
Refactor: consolidate_duplication — plugins/ndf/scripts/supervise_lib…
takemi-ohama Nov 1, 2026
9e28a3c
Fix: 検証の失敗を直す — plugins/ndf/scripts/lib/sprint_loop.py#cmd_sprint
takemi-ohama Nov 1, 2026
55507b4
Fix: 検証の失敗を直す — plugins/ndf/scripts/sprint_close_lib/record_find.py#f…
takemi-ohama Nov 1, 2026
3fcdd27
Test: 現状固定テストを足す — plugins/ndf/scripts/lib/sprint_loop.py#gate2_answer
takemi-ohama Nov 1, 2026
df164e8
Refactor: extract_method — plugins/ndf/scripts/lib/sprint_loop.py#gat…
takemi-ohama Nov 1, 2026
5cf9281
Refactor: extract_method — plugins/ndf/scripts/sprint-close.py#_closi…
takemi-ohama Nov 1, 2026
4375d8d
Refactor: flatten_conditional — plugins/ndf/scripts/supervise_lib/que…
takemi-ohama Nov 1, 2026
b7171f1
Test: 現状固定テストを足す — plugins/ndf/scripts/lib/release_version.py#bump_check
takemi-ohama Nov 1, 2026
ad2116c
Refactor: flatten_conditional — plugins/ndf/scripts/lib/release_versi…
takemi-ohama Nov 1, 2026
e633eca
Refactor: extract_method — plugins/ndf/scripts/lib/sprint_loop.py#cmd…
takemi-ohama Nov 1, 2026
21e70ab
Refactor: extract_method — plugins/ndf/scripts/release-steps.py#cmd_r…
takemi-ohama Nov 1, 2026
a2c8d6b
Fix: 検証の失敗を直す — plugins/ndf/scripts/release-steps.py#cmd_release
takemi-ohama Nov 1, 2026
a258c05
Refactor: extract_method — plugins/ndf/scripts/supervise_lib/queue.py…
takemi-ohama Nov 1, 2026
6a0f786
Test: 現状固定テストを足す — plugins/ndf/scripts/lib/sprint_loop.py#resume_stopped
takemi-ohama Nov 1, 2026
719fcb3
Refactor: replace_with_lookup_table — plugins/ndf/scripts/lib/sprint_…
takemi-ohama Nov 1, 2026
54f9288
Fix: 検証の失敗を直す — plugins/ndf/scripts/lib/sprint_loop.py#resume_stopped
takemi-ohama Nov 1, 2026
62f27fe
Fix: 配布不要の実行の条件を版の照会より先に打つ(#2164)
takemi-ohama Nov 1, 2026
b88f88f
Fix: まとめへ周回の版を明示の版として渡さない(#2164)
takemi-ohama Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions docs/specifications/ndf-production-release-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,20 @@ python3 release-steps.py record --version <版> --prs <PR番号>... [--plugin <
### まとめのプランの記録の PR と `release-verify`

まとめのプラン(`supervise_lib/sprint.py` の `close_plan`)は、記録の PR の参照を経路から決め(`supervise_lib/sprint_routes.py` の
`record_pr_ref`)、記録の PR が `{queue_pr:…}` で決まる経路ではマージの後・`close` の前に work ステップ `release-verify`(`/ndf:release-verification`)を置く。
`record_pr_ref`)、記録の PR の参照が `0` でない経路ではマージの後・`close` の前に work ステップ `release-verify`(`/ndf:release-verification`)を置く。

| 経路 | `close` の `--record-pr` | `release-verify` |
| --- | --- | --- |
| 雛形(`release.form`) | `{queue_pr:release-prod}` | 置く |
| 昇格(`route_waves` が昇格のプランを置き、開発版のチャネルが手で届ける本番でないとき) | `{queue_pr:promote}` | 置く |
| 経路がすべて届けない経路(none) | `0`(本番の記録なし。条件を見ずに閉じる) | 置かない |
| それ以外(merge・manual・検証の環境だけ・手動反映の本番系の昇格) | `unknown`(記録の置き場が分からない。課題を理由つきの `kept_open` で開いたまま残し、ボードも書かない) | 置かない |
| それ以外(merge・manual・検証の環境だけ・手動反映の本番系の昇格) | `{queue_record}`(まとめを流し始める時点に queue が GitHub の参照から記録の PR を探して埋める。#2230) | 置く |
| 開発ループのまとめ(`new close --pace auto`)で、経路がすべて届けない経路でないとき | 経路にかかわらず `{queue_record}`(承認ゲート 2 の後のまとめは本番のプランと別の queue にあり、`{queue_pr:…}` を解けない) | 置く |

`{queue_record}` は、まとめの課題を閉じる PR とそれを参照する PR のリリース記録のうち、段階が本番か配布なしで `スプリント:` が
その閉じる PR を含む記録を置いた PR の番号で埋まる(`sprint_close_lib/record_find.py`)。見つからない・2 つ以上のスプリントにある・
GitHub を読めなければ、まとめを流さずに止まる(queue の結果は `stopped`、開発ループの周回は失敗で締まる)。まとめのプランは
`sprint-close.py --record-pr unknown` を組まず、`unknown` を渡すのは手で打つ入口と #2230 より前に組んだプランだけである。

`release-verify` は、記録の PR にリリース後テストの記録をコメントで置き、課題は閉じない。実行時に番号が `0` になったとき
(最終の検査で変更が無く、まとめの queue の本番が飛ばされたとき)は何もせずに終える。
Expand Down Expand Up @@ -229,10 +235,14 @@ stateDiagram-v2

本番のプランは開発版と同じ `sprint_waves.plan_sprint_release` に `channel="prod"` と `version=prod_version(--version)`(接尾辞を外した版。
`10.18.0-dev.1` → `10.18.0`)を渡して組む。worktree とブランチは `release/v<正式版>`、出す PR は `{queue_pr:check}` である。
`--version` を省いたときは `version` が空で、worktree・ブランチ・承認資料のパスは版の差し込み(`{release_version}`・`{release_base}`)で書き、
プランの「版」の欄の `系列` に開発版のプランの名前 `release` を入れる。キューが本番のプランを流す直前に、開発版のプランの版の記録(`version.json`)の
`base` で埋める(#2164)。
雛形(`release_templates.plan_release`)が組んだステップを目録の側で書き換えず、`new release --version <正式版> --prs {queue_pr:check} --channel prod`
と同じ出力に `課題` が入る(スプリントの工程は雛形に対して順応者の関係にある)。

承認ゲート 2 の文は、開発版の配布が書いた承認資料(元のリポジトリの下の `issues/approval-<プラグイン>-v<正式版>.md` の絶対パス)を示して
承認ゲート 2 の文は、開発版の配布が書いた承認資料(元のリポジトリの下の `issues/approval-<プラグイン>-v<正式版>.md` の絶対パス。版を明示しなかったときは
`v<base>` と書き、`<base>` が開発版のプラン `release` の状態ディレクトリの `version.json` の `base` であることを添える)を示して
本番への配布の承認を取ることを書く。`--state` を渡さないときは、承認されたら `release-steps.py approve --approval <承認資料> --approved-sha <approval-facts の metrics.approved_sha> --by user`
で承認の記録を書いてから「本番」のステージの `command` を打つこと(差し戻されたら打たない)を書く。`--state` を渡したときは、利用者が答えたら
`sprint-state.py gate <状態> "関門 2" --what <要約> --by user --outcome approved|rejected` を打ち、承認されたら「本番」のステージの `command` を打つことと、
Expand All @@ -247,7 +257,7 @@ stateDiagram-v2
| --- | --- | --- |
| N1 | 「本番」のステージは `then_of` を持たず、どの queue の `--then` にも入らない(承認ゲート 2 は利用者が答える。連結すると承認を待たずに本番が流れる) | テストで落とす |
| N2 | 並びは「配布」→「`関門 2`」→「本番」で、間に他のステージが入らない | テストで落とす |
| N3 | 本番のプランの版は `--version` から接尾辞を外したもの、チャネルは `prod`、出す PR は `{queue_pr:check}` | テストで落とす |
| N3 | 本番のプランの版は `--version` から接尾辞を外したもの(`--version` を省けば版の差し込みで、開発版の版の記録の `base` で埋まる)、チャネルは `prod`、出す PR は `{queue_pr:check}` | テストで落とす |
| N4 | `--state` を渡しても、本番のプランは MVV 判定のステップ(`mvv`・`note`・`handoff`)を持たない(`advise` は `channel` が `dev` のときだけ渡す) | テストで落とす |
| N5 | 「`関門 2`」を置くとき、承認ゲート 2 の文はその `gate` の 1 か所にだけあり、「配布」の `note` に重ねない。ほかの経路(N6 と `route_waves`)では「配布」か経路のステージの `note` が正本である | テストで落とす |
| N6 | 本番のブランチが決まっていないときは「`関門 2`」と「本番」を置かず、「配布」で終える(`--state` なら `note` に `normal_gate_2` の文)。`next` に置かなかった理由を 1 文足す(`no_prod_stage`) | テストで落とす |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

スプリントの機械の判定が、記録の無い状態や「確かめる中身が無い」行を取り違えないようにする決まりを 2 つ置く。

- **記録の置き場が分からないまとめの `close` は、課題を閉じない。** リリースの経路が雛形(`release.form`)でも昇格(promote)でも
なく、届ける経路を 1 つでも含むとき、まとめのプランは `sprint-close.py --record-pr unknown` を打つ(`new close --record-pr <番号>`
で組んだときはその番号を打つ。#2089)。`sprint-close.py` は
配布の記録を読まず、どの課題も閉じず、ボードも書かずに、`--issues` の課題を理由つきの `kept_open` で返す(終了コード 0)
- **記録の置き場が分からない `close` は、課題を閉じない。** `sprint-close.py --record-pr unknown` は
配布の記録を読まず、どの課題も閉じず、ボードも書かずに、`--issues` の課題を理由つきの `kept_open` で返す(終了コード 0)。
#2230 から、まとめのプランは `unknown` を組まない。リリースの経路が雛形(`release.form`)でも昇格(promote)でもなく、届ける経路を
1 つでも含むとき(と開発ループのまとめ)は `--record-pr {queue_record}` を組み、まとめを流し始める時点に queue が記録の PR を探して埋める
([ndf-production-release-record.md](ndf-production-release-record.md) の「まとめのプランの記録の PR と `release-verify`」)。
`unknown` を渡すのは手で打つ入口と、#2230 より前に組んだまとめのプランだけである
- **「手動確認は無い」と書いた行は、手動確認の行として数えない。** 要求の「検証手段」の表で 2 列目が「無し」の形の行は、
PR 本文の `## 手動確認` の節に載らず、merge-gate も承認ゲート(終了コード 10)で止まらない

Expand Down Expand Up @@ -51,7 +53,7 @@
| # | 条件 | 破れたときの扱い |
| --- | --- | --- |
| I1 | まとめのプランの記録の参照が `0`(`RECORD_NONE`)になるのは、リリースの経路がすべて届けない経路(`STAGE_NONE`)のときだけである | テストが落とす |
| I2 | 記録の参照が `{queue_pr:…}` でない(`has_record` が偽)とき、プランに `release-verify` を置かず、merge の次は `retro`(その次が `close`。#2228)になる | テストが落とす |
| I2 | 記録の参照が `0` のとき(`has_record` が偽。#2230 からは `0` のときだけ偽)、プランに `release-verify` を置かず、merge の次は `retro`(その次が `close`。#2228)になる | テストが落とす |
| I3 | `--record-pr unknown` の実行は、どの課題も閉じず、ボードも書かず、課題の本文も読まない(gh へ書き込まない) | テストが落とす |
| I4 | `--record-pr 0` の意味(記録を読まず、閉じる条件 1・2 を見ずに `--issues` を閉じる(条件 3 の振り返りの記録は見る)。`--issues` が無ければ終了コード 2)は変わらない | 既存のテストが落とす |
| I5 | 要求の 2 列目が「無し」の形の行は `ManualRow` にならない。それ以外の空でない 2 列目は手動確認の行になる | テストが落とす |
Expand All @@ -66,10 +68,11 @@
| --- | --- |
| 雛形の経路がある | `{queue_pr:release-prod}` |
| 昇格の経路があり、開発版のチャネルが手動反映の本番系(`delivery.MANUAL_PRODUCTION`)でない | `{queue_pr:promote}` |
| 経路がすべて `STAGE_NONE`(`delivery` が `[]` を含む) | `0`(`RECORD_NONE`) |
| それ以外(merge・手で届ける・検証の環境だけ・手動反映の本番系の昇格) | `unknown`(`RECORD_UNKNOWN`) |
| それ以外(merge・手で届ける・検証の環境だけ・手動反映の本番系の昇格) | `{queue_record}`(`RECORD_FOUND`。#2230) |

語 `0` と `unknown` と `has_record` は `supervise_lib/sprint_routes.py` に置き、`close_plan` はそれを呼ぶだけにする。
#2230 から、最初に経路がすべて `STAGE_NONE`(`delivery` が `[]` を含む)かを見て `0`(`RECORD_NONE`)を返し、次に開発ループのまとめ
(`--pace auto`)なら `{queue_record}` を返し、その後に上の表を上から見る。`unknown`(`RECORD_UNKNOWN`)は `sprint_routes.py` から消えた。
語 `0` と `{queue_record}` と `has_record` は `supervise_lib/sprint_routes.py` に置き、`close_plan` はそれを呼ぶだけにする。

#### `sprint-close.py --record-pr`

Expand Down Expand Up @@ -105,17 +108,19 @@

```mermaid
flowchart TD
A["record_pr_ref"] --> B{"雛形の経路がある"}
A["record_pr_ref"] --> D{"経路がすべて STAGE_NONE"}
D -- はい --> Z["0"]
D -- いいえ --> L{"開発ループのまとめ(--pace auto)"}
L -- はい --> U["{queue_record}"]
L -- いいえ --> B{"雛形の経路がある"}
B -- はい --> T["{queue_pr:release-prod}"]
B -- いいえ --> C{"昇格の経路があり、手動反映の本番系でない"}
C -- はい --> P["{queue_pr:promote}"]
C -- いいえ --> D{"経路がすべて STAGE_NONE"}
D -- はい --> Z["0"]
D -- いいえ --> U["unknown"]
C -- いいえ --> U
T --> V["merge → release-verify → retro → close"]
P --> V
U --> V
Z --> W["merge → retro → close(release-verify なし)"]
U --> W
```

`sprint-close.py` の中では、`cmd_close` が `--issues` の有無を確かめ、`_read_sprint_record` が `0` と `unknown` で記録を読まずに
Expand All @@ -130,7 +135,7 @@ PR の一覧を空で返す。`_closing_blocker` は `unknown` のとき全課
| 決定 | 理由 | 採らなかった案 |
| --- | --- | --- |
| `--record-pr` に語 `unknown` を足し、`0` の意味は変えない | 語ならプランの `cmd` と結果を読む人がそのまま意味を取れる。`0` を手で打つ既存の手順の意味が黙って変わらない | 負の数(`-1`)で表す。`0` を「置き場を知らない」に変え、配布なしに別の値を足す |
| 検証の環境だけ(本番の行の無い)経路・手動反映の本番系の昇格も `unknown` にする | 開いたまま残った課題は人が 1 回の操作で閉じられるが、条件を見ずに閉じた課題は確かめていないことが結果から読めない | 検証の環境だけの経路を配布なしとして `0` で閉じる |
| 検証の環境だけ(本番の行の無い)経路・手動反映の本番系の昇格も `unknown` にする(#2230 で `{queue_record}` に置き換わった。閉じる条件を見ずに閉じない方針は変わらない) | 開いたまま残った課題は人が 1 回の操作で閉じられるが、条件を見ずに閉じた課題は確かめていないことが結果から読めない | 検証の環境だけの経路を配布なしとして `0` で閉じる |
| 「無し」の判定を `rows_of` の 1 か所に置き、語の直後を括弧・句読点・空白・文末に限る | PR 本文の節も merge-gate の数え方も `rows_of` の出力から作られる。後続を限れば「無しの場合は〜」のような確認の文を落とさない | merge-gate で「無し」の行を数えない(PR 本文に未チェックの行が残り続ける)。要求の雛形の文を変える(雛形に「無ければ行を消す」が既にある) |

## データ・設定
Expand All @@ -157,7 +162,7 @@ PR の一覧を空で返す。`_closing_blocker` は `unknown` のとき全課

| 観点 | テスト |
| --- | --- |
| merge・手で届ける・検証の環境だけの経路で、`close` の `cmd` が `--record-pr unknown` になり `release-verify` が無いこと(I1・I2) | `test_supervise_pace_verify.py` の `test_close_without_a_known_record_keeps_the_issues_open` |
| merge・手で届ける・検証の環境だけの経路で、`close` の `cmd` が `--record-pr {queue_record}` になり `unknown` を持たず、`release-verify` が同じ参照を持つこと(I1・I2。#2230) | `test_supervise_pace_verify.py` の `test_close_without_a_plan_record_resolves_it_when_run` |
| `delivery: []` で `--record-pr 0` のまま変わらないこと(I1) | 同じファイルの `test_close_of_no_delivery_keeps_record_pr_zero` |
| `--record-pr unknown --issues …` で全課題が `kept_open`・理由つき・終了コード 0、gh の書き込みが 0 回で、`summary` が先頭の文を持つこと(I3) | `test_sprint_close_issues.py` の `test_record_unknown_keeps_the_given_issues_open_with_a_reason` |
| `unknown` に `--issues` が無ければ終了コード 2、それ以外の値・負の数は終了コード 3 | 同じファイルの `test_record_unknown_alone_returns_two`・`test_record_pr_rejects_other_values` |
Expand All @@ -170,15 +175,13 @@ PR の一覧を空で返す。`_closing_blocker` は `unknown` のとき全課

| 項目 | 内容 |
| --- | --- |
| 記録の PR を `close` へ渡す手段が無い | merge・手で届ける・検証の環境だけの経路の課題は、`unknown` で開いたまま残り、人が手で閉じる。受け渡しの手段は課題 #2044 が扱う |
| 手動反映の本番系の昇格はテストで縛っていない | 見本のリポジトリ(`make_repo`)は起点 develop・本番 main で、起点と本番が同じ形を組めない。`record_pr_ref` の分岐(`manual_prod`)は昇格を飛ばして `unknown` へ落ちる形で入っている |
| 語 `unknown` が 2 か所にある | `sprint-close.py` は `supervise_lib` を import しない独立のスクリプトで、`RECORD_UNKNOWN` を `sprint_routes.py` と別に持つ(コメントで指し合う) |
| 手動反映の本番系の昇格はテストで縛っていない | 見本のリポジトリ(`make_repo`)は起点 develop・本番 main で、起点と本番が同じ形を組めない。`record_pr_ref` の分岐(`manual_prod`)は昇格を飛ばして `{queue_record}` へ落ちる形で入っている |
| 既に閉じた課題も `kept_open` で載る | `unknown` は課題の状態を読まずに返すため、closing keywords で GitHub が先に閉じた課題も `kept_open` に並ぶ |
| 流し直さない PR 本文 | 既に作られた PR 本文の「無し」の未チェック行は、pr ステップを流し直さない限り残る |

## 関連リンク

- 課題: #1875(記録の置き場が分からない close)・#1675(「無し」の手動確認の行)。実装は PR #2051
- 課題: #1875(記録の置き場が分からない close)・#1675(「無し」の手動確認の行)。実装は PR #2051。まとめのプランが `unknown` の代わりに `{queue_record}` を組む変更は #2230
- [ndf-production-release-record.md](ndf-production-release-record.md): 経路ごとの記録の PR と `release-verify`
- [ndf-sprint-close-acceptance-criteria.md](ndf-sprint-close-acceptance-criteria.md): 閉じる条件 2 と受け入れ条件の印(`unknown` で本文を読まない条件 I8)
- [ndf-sprint-close-referenced-issues.md](ndf-sprint-close-referenced-issues.md): 参照だけの課題(`unknown` ではスプリントの PR を読まない)
Expand Down
Loading
Loading