Repository navigation
Description
何を見つけたか
リリース後テストの記録の 対象の版: を v10.26.1(…) と v を付けて書くと、sprint-close.py --with-verification がそのブロックを読めず、kept_open・理由「本番の版のリリース後テストの記録が無い」を返す。
- 配布の記録(PR Release: ndf v10.26.1 #2218 の本文)は
版: 10.26.0 → 10.26.1で、lib/dist_record.pyのparse_recordは本番の版を10.26.1と読む - リリース後テストのコメント(Release: ndf v10.26.1 #2218 (comment) )は
対象の版: v10.26.1(2026-10-31 08:52 JST に…)で、_strip_noteの後はv10.26.1になる _pick_verify_blockはb["ver"] == versionの完全一致で探し、外れると「対象の版が版数でないブロック」だけへ落とす。v10.26.1は_EXPLICIT_VERSION(v?\d+\.\d+\.\d+)に当たるため、そこでも外れてNoneになる
実行: python3 sprint-close.py --record-pr 2218 --with-verification(2026-10-31、ndf 10.26.1)→ {"number": 2171, "result": "kept_open", "reason": "本番の版のリリース後テストの記録が無い"}
どこで見つけたか
#2171 の振り返りの後の「スプリントを閉じる」(progress-tracking)。plugins/ndf/scripts/lib/dist_record.py の _pick_verify_block(develop では 115〜128 行)と _strip_note(47〜49 行)、plugins/ndf/skills/release-verification/SKILL.md の 115 行(対象の版: <配布した版>(<配布した時刻>))
なぜこの変更の範囲外なのか
#2171 の受け入れ条件は factory/ の契約と受け口だけで、NDF の配布の記録の読み取りを含まない。#2171 は実環境の保留 5 行で開いたままにする判断のため、この不具合が今回の結論を変えてはいない。根拠: NDF の共通原則の「判断の範囲は目の前の変更・操作に限る」(MVV 版 3)
直さないと何が起きるか
リリース後テストの書き手が v を付けると、すべての条件が合格でも課題が閉じず、受け入れ条件の印も付かない。理由の文が「記録が無い」のため、書いた記録が読めていないことに気づきにくい。
起票者の推定
題・本文のうち、利用者の指示の原文に無く起票者が推して足した条件。承認ゲート 1 で利用者が確かめるまで、利用者の決定として扱わない。
| # | 条件 | 推した出所 | この要求での扱い |
|---|---|---|---|
| S1 | 直し方として、版の比較の前に先頭の v を落としてそろえる形が考えられる |
dist_record.py を読んだ起票者の判断 |
受け入れ条件 1〜3。対象の版だけでなく本番の版にも同じ規則を当て、規則はリリース記録を読む共通の部品の 1 か所に置く(前提 2・3) |
| S2 | #2170 の記録(PR #2195 のコメント)も同じ書き方で、同じ理由で閉じなかった可能性がある | 起票者の推定(確かめていない) | 2026-11-05 に確かめた。PR #2195 のリリース後テストの記録は 対象の版: v10.26.0(…) で、sprint-close.py --record-pr 2195 --with-verification --dry-run は #2170 に理由「本番の版のリリース後テストの記録が無い」を返す。受け入れ条件 8 |
由来
PR #2218
依頼(原文)
依頼の原文は、この本文の上の「何を見つけたか」から「由来」までの節である(書き手: 起票者、日付: 2026-10-31。#2171 の振り返りの後の「スプリントを閉じる」で、課題を書いた AI が不具合の記録として書いた。利用者の指示の原文ではない)。
人へ問わずに進め、決められない点は前提か未決として課題の本文へ書く。
(書き手: AI の起動指示、日付: 2026-11-05。この要求を書く工程の起動指示)
解釈: リリース後テストの記録の書き手が「対象の版」を v10.26.1 のように先頭に v を付けて書いても、v を付けない 10.26.1 と同じ版として読まれ、スプリントを閉じる判定(課題を閉じる・受け入れ条件に印を付ける)に使われるようにする。
目的
- リリース後テストで全条件が合格した課題が、版の書き方(先頭の
vの有無)だけを理由に開いたまま残らない状態にする - 書いた記録が読まれなかった理由を、「記録が無い」と取り違えずに済む状態にする
用語
| 用語 | 意味 |
|---|---|
| リリース記録 | 本番へ出したときに、記録の PR へ書く ## 配布の記録 の見出しのブロック。版: <前の版> → <出した版> の行を持つ |
| リリース後テストの記録 | 記録の PR へコメントで投稿する ## リリース後テスト の節。対象の版: の行と合否の表を持つ |
| 対象の版 | リリース後テストの記録の 対象の版: の行に書く版。全角の括弧から後ろは注記として読まない |
| 本番の版 | リリース記録の 版: の行の → の右に書く版。全角の括弧から後ろは注記として読まない |
| 版の表記の揺れ | 同じ版を指す書き方の違いのうち、この課題が扱うもの。先頭の小文字の v の有無だけを指す |
前提
- 前提 1: そろえる表記の揺れは、版の先頭の小文字の
v1 文字の有無だけである。大文字のV、ndf--v10.26.1のようなタグ名、前後の余分な語は、この課題では版として読まない(いずれも記録の書き方の手順release-verificationが示す形対象の版: <配布した版>(<配布した時刻>)から外れる。実際に書かれた例は PR Release: ndf v10.26.0 #2195・PR Release: ndf v10.26.1 #2218 のv付きの 2 件だけで、ほかの形は見つかっていない) - 前提 2: 先頭の
vを落とす規則は、対象の版と本番の版の両方へ同じように当てる。読み取りの規則を 1 か所(リリース記録を読む共通の部品)に置き、比べる側ごとに写さない - 前提 3: 本番の版の読み取り結果(スプリントを閉じる処理・リリース記録の重複の確認・プランの版の差し込みが使う値)は、
版:の行にvが付いていてもvを付けない形で返す。これらの使い手はvを付けない版を前提に比べている(リリース記録を書く側はvを付けずに書く)ため、返す形を変えても既存の記録の読み取り結果は変わらない - 前提 4: この課題は柱の課題 機械が読む出力を 1 行 JSON にそろえ、Markdown と本文の見出しから判定しない #2340(機械が読む出力を 1 行 JSON にそろえ、本文の見出しから判定しない)の子の課題である。機械が読む出力を 1 行 JSON にそろえ、Markdown と本文の見出しから判定しない #2340 は人が書いた本文から読む値を機械用のブロックへ移す。この課題は移す前の今の読み取りで、表記の揺れを吸収するところまでを扱う。機械が読む出力を 1 行 JSON にそろえ、Markdown と本文の見出しから判定しない #2340 の仕組みが入った後も、この課題の受け入れ条件 7・8 の再現の手順は 機械が読む出力を 1 行 JSON にそろえ、Markdown と本文の見出しから判定しない #2340 の子の課題の確認にそのまま使える
- 前提 5: リリース後テストの記録の書き方の手順(
release-verificationの「出力物」)は変えない。読む側がvの有無を吸収するので、書き手へvを付けないよう求める規則を足さない(Value 5: 要らない決まりを足さない)
対象範囲
含む:
- 対象の版と本番の版を比べるときに、先頭の
vの有無を同じ版として扱うこと - 本番の版の読み取り結果を、
vを付けない形にそろえること - PR Release: ndf v10.26.1 #2218(NDF Factory: contracts と進捗の受け口 #2171)と PR Release: ndf v10.26.0 #2195(NDF Factory: Cognito の認証(Google・GitHub)とプランごとの利用量 #2170)の記録が、本番の版のリリース後テストの記録として読まれることの確認
含まない:
- 実際に版数が食い違う記録(対象の版を
10.26.2と誤記したなど)で出る理由の文「本番の版のリリース後テストの記録が無い」を言い換えること。原因が書き手の誤記であり、表記の揺れとは別の不具合である。本文の値を機械用のブロックへ移す 機械が読む出力を 1 行 JSON にそろえ、Markdown と本文の見出しから判定しない #2340 で扱う - 大文字の
V・タグ名など、前提 1 の外の書き方を読むこと - リリース後テストの記録の書き方の手順の変更(前提 5)
- NDF Factory: Cognito の認証(Google・GitHub)とプランごとの利用量 #2170 を閉じること。この課題の修正が入った後に、NDF Factory: Cognito の認証(Google・GitHub)とプランごとの利用量 #2170 のスプリントを閉じる工程で判定する
- 設計のクラス図と非機能設計表。変更はリリース記録を読む共通の部品の関数の中に収まり、型(クラス)を足さず変えない。仕様に非機能の条件が無い
ドメインイベント
| # | イベント | 引き金 | 失敗したとき | 順序の前提 |
|---|---|---|---|---|
| E1 | リリース記録を記録の PR へ書いた | 本番への配布(release) |
記録が無ければ、スプリントを閉じる処理は課題を閉じない(今の振る舞いのまま) | — |
| E2 | リリース後テストの記録をコメントで投稿した | リリース後テストの実施(release-verification) |
記録が無ければ、開いたままにして理由「本番の版のリリース後テストの記録が無い」を返す(今の振る舞いのまま) | E1 |
| E3 | 本番の版と対象の版を、先頭の v を落としてから比べた |
スプリントを閉じる処理(sprint-close.py --with-verification)の実行 |
一致するブロックが無ければ、今の規則(最後のリリース記録より後で、対象の版が版数でない最後のブロック)へ落とす | E1・E2 |
| E4 | 一致したブロックの合否の表で、課題を閉じるかを判定した | E3 でブロックが選ばれた | 合格の行が足りなければ開いたままにする(今の振る舞いのまま) | E3 |
E3 だけが変わる。E1・E2・E4 の振る舞いは変えない。
受け入れ条件
- 1. リリース記録の
版:が10.26.0 → 10.26.1で、リリース後テストの記録の対象の版:がv10.26.1(注記)のとき、リリース記録の読み取り(parse_record)は、そのリリース後テストのブロックを使うブロックとして返す - 2. リリース記録の
版:がv10.26.0 → v10.26.1で、対象の版:が10.26.1のときも、受け入れ条件 1 と同じブロックを返す。このとき読み取った本番の版は10.26.1(vを付けない)である - 3. 開発版の版数でも同じに扱う:
版:の出した版が10.17.69-dev.1で対象の版:がv10.17.69-dev.1のとき、そのブロックを返す - 4. 退行しない:
対象の版:がv10.17.69-dev.1で本番の版が10.17.68のときは、そのブロックを本番の検証に使わない(版数の違うテストを使わない規則を保つ) - 5. 退行しない: 本番の版に一致するブロックが無く、対象の版が版数でない(
main c427284など)ブロックが最後のリリース記録より後にあるときは、今と同じくそのブロックを返す(sprint-close: 版数を上げない配布で、配布の記録の「版」とリリース後テストの「対象の版」の形が違い、スプリントの課題をすべて kept_open にする #1789 の規則を保つ)。段階が「配布なし」の記録の選び方も変わらない - 6. リリース記録を書く側が書いた記録(
vを付けない版)を読んだ結果は、修正の前後で変わらない。リリース記録の重複の確認(同じ版・同じ PR の記録が既にあるか)とプランの版の差し込みの既存のテストが、修正の後も通る - 7.
python3 plugins/ndf/scripts/sprint-close.py --record-pr 2218 --with-verification --dry-runの出力で、NDF Factory: contracts と進捗の受け口 #2171 の行の理由が「本番の版のリリース後テストの記録が無い」でない - 8.
python3 plugins/ndf/scripts/sprint-close.py --record-pr 2195 --with-verification --dry-runの出力で、NDF Factory: Cognito の認証(Google・GitHub)とプランごとの利用量 #2170 の行の理由が「本番の版のリリース後テストの記録が無い」でない
影響
| 対象 | 影響 |
|---|---|
| 公開インタフェース | 変わらない。スプリントを閉じる処理の引数と結果の JSON の形はそのまま |
| データ | 変わらない。記録の書き方と既存の記録はそのまま |
| 既存の振る舞い | v 付きの対象の版・本番の版を書いた記録が、v を付けない記録と同じに読まれる。v を付けない記録の読み取り結果は変わらない(受け入れ条件 6) |
検証手段
| 項目 | 手段 |
|---|---|
| テスト | uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests -q -n 4(受け入れ条件 1〜6 はリリース記録の読み取りの単体テストで確かめる) |
| 静的解析 | リポジトリの継続的統合が走らせる検査(ruff など)をそのまま使う |
| 手動確認(マージ前) | 受け入れ条件 7・8 の読むだけの実行(--dry-run)を、修正したブランチの作業ディレクトリで打ち、理由の文を確かめる。課題もボードも書き換えない |
修正の前の実測(2026-11-05、develop の ffa7e1cf8): 受け入れ条件 7 のコマンドは {"number": 2171, "result": "kept_open", "reason": "本番の版のリリース後テストの記録が無い"}、受け入れ条件 8 のコマンドは {"number": 2170, "result": "kept_open", "reason": "本番の版のリリース後テストの記録が無い"} を返した。同じ形の記録を組んで parse_record を呼ぶと、対象の版: 10.26.1 ではブロックが返り、対象の版: v10.26.1 では返らない(verify_block が None)。
前提とする取り決め
| 項目 | 参照先 / 決めたこと |
|---|---|
| プロジェクト構造 | リリース記録の形は plugins/ndf/scripts/lib/dist_record.py が 1 か所で持つ(モジュールの冒頭の説明)。版の表記をそろえる規則もここに置き、ほかのモジュールへ写さない |
| コーディング規約 | AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストを書かない |
| テスト戦略 | リリース記録の読み取りの単体テスト(plugins/ndf/scripts/tests/)で受け入れ条件 1〜6 を固定する。受け入れ条件 7・8 は実際の記録に対する読むだけの実行で確かめる |
境界
| 区分 | 内容 |
|---|---|
| 常に行う | 既存のテストの実行、受け入れ条件 7・8 の読むだけの実行 |
| 確認してから行う | なし(公開インタフェース・依存・データの変更を伴わない) |
| 行わない | --dry-run を外した実行(課題を閉じる・ボードを書く)、#2170 を閉じること、リリース後テストの記録の書き方の手順の変更、#2340 の機械用のブロックへの移行 |
未決
無し。決められない点は前提 1〜5 に書いた。
進行
モード: — / 進め方: auto
- 要求と受け入れ条件 — 2026-11-05 22:27
- 作業場所の用意 — 2026-11-06 00:04
- 設計 — 2026-11-05 22:31
- 素材の収集と出典の確定
- ドキュメント再構成
- ドキュメントレビュー
- 計画 — 2026-11-06 00:04
- 実装 — 2026-11-06 00:04
- 構造改善 — 2026-11-06 01:22
- 実装レビュー — 2026-11-06 01:22
- 完了判定 — 2026-11-06 00:25
- Pull Request — 2026-11-06 01:06
- 確定仕様化
- 後片付け
- 配布
- 体裁レビュー
- リリース後テスト
- 振り返り
- 棚卸し
Activity
docs(#2225): 不変条件 I2 を版数の対象の版に限り、I3 のフォールバックと両立させる
Merge pull request #2628 from devbasex/design/issue-2225
Merge pull request #2650 from devbasex/feat/issue-2225-lroot3-19