Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
11 commits
Select commit Hold shift + click to select a range
fe3eb61
Add: 既定ブランチ宛の PR の本文の closing keywords を閉じる予定の参照へ置き換える(#2228・#2082)
takemi-ohama Oct 31, 2026
1dea1b7
Add: sprint-close.py が最終工程の記録を確かめてから課題を閉じる(#2228・#2119)
takemi-ohama Oct 31, 2026
17fd3ef
Change: まとめのプランを振り返り → 課題を閉じる → 棚卸しの順にする(#2228・#2119)
takemi-ohama Oct 31, 2026
522fc96
Refactor: 既定ブランチ宛の置き換えの判定を lib/closing.py の defer_for_base に寄せる(#2228)
takemi-ohama Oct 31, 2026
fea8391
Docs: 課題を閉じる時点の正本を progress-tracking の「スプリントを閉じる」に置き、呼ぶ側はそこを指す(#2228)
takemi-ohama Oct 31, 2026
ad52193
Docs: docs/glossary.md を用語集から作り直す(#2228)
takemi-ohama Oct 31, 2026
bf6f06b
Refactor: sprint-close.py の最終工程の判定と課題の集め方を sprint_close_lib へ、pr-step…
takemi-ohama Oct 31, 2026
0196004
Merge origin/sprint/m26-2 into feat/issue-2228-m26-2
takemi-ohama Oct 31, 2026
6e6361a
Merge remote-tracking branch 'origin/sprint/m26-2' into feat/issue-22…
takemi-ohama Oct 31, 2026
10fa6af
Docs: 確定仕様のまとめのプランの並びと閉じる条件・閉じる予定の参照を #2228 の振る舞いに合わせる
takemi-ohama Oct 31, 2026
70158f2
docs: doc-lint のヒット(課題番号の由来・比較の語)を今の決まりの形へ直す
takemi-ohama Oct 31, 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
2 changes: 1 addition & 1 deletion docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ NDF が提供する工程・承認ゲート・モード・ステップの語。d
| 欠け | `gaps` | 結果 JSON の gaps の 1 件。出すはずだったのに出せなかった材料・記録、届かなかった目標を、種類・名前・理由で書く | — | — | `docs/specifications/ndf-step-result-gaps-and-reading.md` |
| 過程の項目 | `process` | 結果 JSON の process。スクリプトが実行したこと(コマンド・操作)と、その結果の要旨を順に並べる | — | — | `docs/specifications/ndf-step-result-gaps-and-reading.md` |
| 判断の項目 | `decisions` | 結果 JSON の decisions。スクリプトが決めたことと、その根拠を並べる | — | — | `docs/specifications/ndf-step-result-gaps-and-reading.md` |
| 最終工程の記録 | — | 最終工程を終えたことを示す、GitHub に残った記録。配布は配布の記録の `段階:`、リリース後テストはその課題の行、振り返りは課題の本文の `振り返り: <コメントの URL>` の行。sprint-close.py が閉じる前に確かめる | — | — | `plugins/ndf/skills/progress-tracking/SKILL.md` |
| 最終工程の記録 | — | 最終工程を終えたことを示す、GitHub に残った記録。配布は配布の記録の `段階:`、リリース後テストはその課題の行、振り返りは課題の本文の `振り返り: <コメントの URL>` の行のうち、指すコメントの識別子が記録の PR の最後の配布の記録のコメントの識別子以上のもの(その実行の振り返り)。sprint-close.py が閉じる前に確かめる | — | — | `plugins/ndf/skills/progress-tracking/SKILL.md` |
| 閉じる予定の参照 | — | Pull Request の本文に `最終工程の後に閉じる: #<番号>` と書く形。GitHub は閉じず、sprint-close.py がスプリント課題として集める。宛先が既定ブランチの Pull Request では、NDF の手順が closing keywords をこの形へ置き換える | — | — | `plugins/ndf/skills/progress-tracking/SKILL.md` |

## NDF の Slack 通知(`ndf-notification`)
Expand Down
2 changes: 1 addition & 1 deletion docs/glossary/glossary.json
Original file line number Diff line number Diff line change
Expand Up @@ -4670,7 +4670,7 @@
{
"term": "最終工程の記録",
"context": "ndf-workflow",
"meaning": "最終工程を終えたことを示す、GitHub に残った記録。配布は配布の記録の `段階:`、リリース後テストはその課題の行、振り返りは課題の本文の `振り返り: <コメントの URL>` の行。sprint-close.py が閉じる前に確かめる",
"meaning": "最終工程を終えたことを示す、GitHub に残った記録。配布は配布の記録の `段階:`、リリース後テストはその課題の行、振り返りは課題の本文の `振り返り: <コメントの URL>` の行のうち、指すコメントの識別子が記録の PR の最後の配布の記録のコメントの識別子以上のもの(その実行の振り返り)。sprint-close.py が閉じる前に確かめる",
"source": "plugins/ndf/skills/progress-tracking/SKILL.md"
},
{
Expand Down
6 changes: 3 additions & 3 deletions docs/specifications/ndf-backlog-refinement-stage.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ conductor が打ち切った。今の形では次のように動く。

### スプリントの終わりのプランの `refine` ステップ

`supervise.py new close` が組むプラン(`supervise_lib/sprint.py` の `close_plan`)は、`retro` の後に
`refine` を置く。`retro` の `next` は `refine` で、`retro` の `prompt` は棚卸しを含まない。
`supervise.py new close` が組むプラン(`supervise_lib/sprint.py` の `close_plan`)は、`retro` の後に課題を閉じる `close` を、
その後に `refine` を置く。`retro` の `next` は `close`、`close` の `next` は `refine` で、`retro` の `prompt` は棚卸しを含まない。

| キー | 値 |
| --- | --- |
Expand Down Expand Up @@ -131,7 +131,7 @@ worker の歯止めで、費用の上限は件数が持つ。プランの `上
| 不正な上限は候補を集めずに終了コード 2 | 同上の `test_candidates_reject_invalid_limit_before_collecting` |
| 候補が 0 件の棚卸しは上限の導入で持ち越しにならない | 同上の `test_candidates_zero_is_ok_under_limit` |
| 書き込み先・plan の `repo`・記録のどれかが食い違えば、1 件も書かずに終了コード 3 | 同上の `test_apply_refuses_*` |
| `new close` のプランで `retro` の次が `refine`、`refine` の `stage` が `棚卸し` で `timeout` を持ち、プロンプトが無人の扱いを渡す | `plugins/ndf/scripts/tests/test_supervise_pace.py`(`test_close_runs_spec_close_and_retro_once_each_in_order`) |
| `new close` のプランで `retro` の次が `close`、その次が `refine`、`refine` の `stage` が `棚卸し` で `timeout` を持ち、プロンプトが無人の扱いを渡す | `plugins/ndf/scripts/tests/test_supervise_pace.py`(`test_close_runs_spec_close_and_retro_once_each_in_order`) |
| `STEP_PHASES` がフェーズの表と一致する | `plugins/ndf/scripts/tests/test_transcript_agents.py`(`test_the_step_names_match_the_phase_table`) |
| `stage 棚卸し` が記録され、5 モードで必須として扱われる | `plugins/ndf/scripts/tests/test_progress_record_stages.py`(`test_the_refinement_stage_is_recorded_and_required_in_every_mode`) |
| 最終工程を持つ 3 つの Skill(`retrospective` / `release-verification` / `release`)が棚卸しを呼ばない。順序の制約と規則 14 がそれぞれ 1 か所にある | 文書を `grep -n` で読んで確かめる(文言を照合するテストは書かない) |
Expand Down
12 changes: 7 additions & 5 deletions docs/specifications/ndf-cleanup-and-bundle-closing.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ Request の head のリモートブランチは、同意を求めずに消す。
有無にかかわらず消さない。

**スプリント課題は、最終工程を出るときに閉じる。** 閉じる条件は「本番リリースまで済んで
いる、またはリリースを飛ばした」と「リリース後テストを通る経路では受け入れ条件がすべて `合格`」の
2 つで、課題ごとに見る。`merged` は課題を閉じない。
いる、またはリリースを飛ばした」と「リリース後テストを通る経路では受け入れ条件がすべて `合格`」と
「その実行の最終工程の記録がある(`--final-stage`、省けば振り返り。#2228)」の 3 つで、課題ごとに見る。`merged` は課題を閉じない。

**リリース記録は Pull Request に置く。** `release` の出力物は会話に出るだけで別の実行からは
読めないため、書く側の形を 1 つに決め、読む側はその形だけを読む。
Expand Down Expand Up @@ -227,7 +227,7 @@ Pull Request を選ぶため、別のスプリント課題を閉じうる。
| `既に閉じていた` | 最初の読みが CLOSED(既定ブランチへのマージで GitHub が先に閉じた場合を含む) |
| `失敗(理由)` | 最後の読みが CLOSED でない、または読み取りが 0 以外で終わった |
| `開いたまま(理由)` | 閉じる条件に当たらない |
| `閉じているが条件を満たさない(理由)`(`closed_unverified`) | 最初の読みが CLOSED で、閉じる条件 2 を満たさない |
| `閉じているが条件を満たさない(理由)`(`closed_unverified`) | 最初の読みが CLOSED で、閉じる条件 2 か 3 を満たさない |

**`失敗` が 1 件でもあれば、最終工程を完了と報告せず、棚卸しへ進まずに止まる。**
`開いたまま` と `閉じているが条件を満たさない` は止める理由にせず、棚卸しへ進んでよい。
Expand Down Expand Up @@ -299,8 +299,10 @@ Pull Request を選ぶため、別のスプリント課題を閉じうる。
一時ディレクトリにあり、共通の git ディレクトリと別のファイルシステムのことがあるため、`mv` が
コピーになる。

**チャネルを分けないリポジトリでは、既定ブランチへのマージで GitHub が先に閉じる。** 「スプリントを
閉じる」は `既に閉じていた` を数えるだけで、二重に閉じようとしても結果は変わらない。
**チャネルを分けないリポジトリでも、NDF の手順で書いた Pull Request の本文では GitHub が先に閉じない。**
既定ブランチ宛の本文の closing keywords は、`pr-steps.py` とプランの pr のステップが閉じる予定の参照
(`最終工程の後に閉じる: #<番号>`)へ置き換える。手で書いた本文・コミットメッセージの closing keywords で
GitHub が先に閉じたときは、「スプリントを閉じる」は `既に閉じていた` を数えるだけで、二重に閉じようとしても結果は変わらない。

## 関連リンク

Expand Down
2 changes: 2 additions & 0 deletions docs/specifications/ndf-sprint-close-referenced-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
語の正本の行は `development-workflow` の
[`references/glossary.md`](../../plugins/ndf/skills/development-workflow/references/glossary.md) にもある。
closing keywords は、Pull Request の本文に課題の番号と一緒に書くと、マージのときに GitHub がその課題を自動で閉じるキーワードである。
閉じる予定の参照(`最終工程の後に閉じる: #12`。既定ブランチ宛の本文で NDF の手順が closing keywords を置き換えた形)も、
`closing-issues.sh` が closing keywords と同じ指し先の規則で本文から集め、参照だけの課題にしない。

## 背景

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@
| # | 条件 | 破れたときの扱い |
| --- | --- | --- |
| I1 | まとめのプランの記録の参照が `0`(`RECORD_NONE`)になるのは、リリースの経路がすべて届けない経路(`STAGE_NONE`)のときだけである | テストが落とす |
| I2 | 記録の参照が `{queue_pr:…}` でない(`has_record` が偽)とき、プランに `release-verify` を置かず、merge の次は `close` になる | テストが落とす |
| I2 | 記録の参照が `{queue_pr:…}` でない(`has_record` が偽)とき、プランに `release-verify` を置かず、merge の次は `retro`(その次が `close`。#2228)になる | テストが落とす |
| I3 | `--record-pr unknown` の実行は、どの課題も閉じず、ボードも書かず、課題の本文も読まない(gh へ書き込まない) | テストが落とす |
| I4 | `--record-pr 0` の意味(記録を読まず、閉じる条件を見ずに `--issues` を閉じる。`--issues` が無ければ終了コード 2)は変わらない | 既存のテストが落とす |
| I4 | `--record-pr 0` の意味(記録を読まず、閉じる条件 1・2 を見ずに `--issues` を閉じる(条件 3 の振り返りの記録は見る)。`--issues` が無ければ終了コード 2)は変わらない | 既存のテストが落とす |
| I5 | 要求の 2 列目が「無し」の形の行は `ManualRow` にならない。それ以外の空でない 2 列目は手動確認の行になる | テストが落とす |

### 入出力の契約
Expand Down Expand Up @@ -112,9 +112,9 @@ flowchart TD
C -- いいえ --> D{"経路がすべて STAGE_NONE"}
D -- はい --> Z["0"]
D -- いいえ --> U["unknown"]
T --> V["merge → release-verify → close"]
T --> V["merge → release-verify → retro → close"]
P --> V
Z --> W["merge → close(release-verify なし)"]
Z --> W["merge → retro → close(release-verify なし)"]
U --> W
```

Expand Down
2 changes: 1 addition & 1 deletion docs/specifications/ndf-workflow-development-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ MVV のレッドラインで人へ戻すという要求がそれを決める。
| --- | --- |
| `sprint-state.py init <state> --name <名>-<n> --pace auto --issue ... --dev V --prod V --goal <再開のコマンド> [--mvv mvv.md --milestone M]` | `--prod` を省けば開発版の接尾辞を外した版 |
| `supervise.py new sprint --pace auto --issue <選んだ課題> --design <承認済みでない課題> [--designed <approved の課題>] ... [<-- の後の引数>]` | `loop answer --approved` で答えた課題は設計のプランを作らず、設計の結果のステージが設計 PR の設計の結果を読む |
| `supervise.py new close --pace auto --issue <選んだ課題> --state <state> [--carry <前の周回の refine.deferred>] [--milestone M]` | まとめのステージ(確定仕様化 → Pull Request → 課題を閉じる → 振り返り → 棚卸し)だけを組む。最終の検査・開発版・本番は置かず、`fast` 節を読まない |
| `supervise.py new close --pace auto --issue <選んだ課題> --state <state> [--carry <前の周回の refine.deferred>] [--milestone M]` | まとめのステージ(確定仕様化 → Pull Request → 振り返り → 課題を閉じる → 棚卸し。#2228)だけを組む。最終の検査・開発版・本番は置かず、`fast` 節を読まない |

`pipeline` は、最初のステージの queue の最後に `--then <まとめのプラン>` をつなぎ、`supervise.py wait <D>` →
`loop lap <名> --done <D>` を続けた 1 行である。手で行うステージか別の queue のステージが残るときは、それを終えてから
Expand Down
2 changes: 1 addition & 1 deletion issues/issue-2228-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
| `scripts/pr-steps.py` | `upsert` で、宛先(新しく作るなら `--base` か起点、既存なら `baseRefName`)が `merge_closes_issues` に当たれば本文を `defer_closing` に通す。置き換えた指し先を `metrics.deferred_closing` に載せる |
| `scripts/supervise_lib/pr.py` | `_publish` で同じ判定と置き換えを行ってから `gh pr create` / `gh pr edit` へ渡す |
| `scripts/supervise_lib/sprint_close_steps.py`・`sprint.py`・`release_templates.py` | まとめのプランの並びを `merge →(release-verify)→ retro → close → refine` にする。`close` は `--final-stage 振り返り` を明示し、`retro` の指示に「課題を閉じない(次の close が閉じる)」を足す |
| `tests/fixtures/supervise-contract/plans/close/4-close.json` | まとめのプランの契約の写しを新しい並びに合わせる |
| `plugins/ndf/scripts/tests/fixtures/supervise-contract/plans/close/4-close.json` | まとめのプランの契約の写しを新しい並びに合わせる |
| `skills/progress-tracking/SKILL.md` の「スプリントを閉じる」 | 閉じる時点の正本。閉じる条件 3・`--final-stage` の値と呼ぶ Skill の対応・閉じる予定の参照・プランの並びを持つ |
| `skills/pr/SKILL.md` の「closing keywords は本文だけに書く」 | 既定ブランチ宛では NDF の手順が置き換えることを書き、閉じる時点は正本を指す |
| `skills/release-verification/SKILL.md`・`retrospective`・`release`・`merged` と `development-workflow` の references(`pace.md`・`loop.md`・`stage-completeness.md`・`glossary.md`) | 閉じる時点・順序・閉じる条件の写しを外し、正本を指す。順序の説明の文を新しい並びに直す |
Expand Down
7 changes: 5 additions & 2 deletions plugins/ndf/scripts/lib/closing-issues.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# NDF plugin: Pull Request の本文から、閉じる語が指す issue を取り出す。
# NDF plugin: Pull Request の本文から、閉じる語と閉じる予定の参照が指す issue を取り出す。
#
# closing-issues.sh [--repo <所有者>/<リポジトリ>] [本文のファイル]
# 引数が無ければ標準入力から読む。`<所有者>/<リポジトリ>` と `<番号>` をタブで
Expand All @@ -16,6 +16,9 @@
#
# 起点ブランチが既定ブランチでないリポジトリでは、マージしても自動クローズが働かない。
# 後片付けの工程がこの一覧を読み、まだ OPEN のものだけを閉じる。
#
# **閉じる予定の参照(`最終工程の後に閉じる: #12`)も同じ指し先の規則で取り出す**(#2228)。
# 既定ブランチ宛の本文では NDF の手順が閉じる語をこの形へ置き換える。形の正本は lib/closing.py の DEFERRED。
set -uo pipefail

DEFAULT_REPO=""
Expand Down Expand Up @@ -46,7 +49,7 @@ body=$(cat -- "${1:--}")
# **Pull Request の URL は拾わない。** 閉じる対象は issue である。
NAME='[A-Za-z0-9._-]+'
REF="(https?://github\.com/$NAME/$NAME/issues/[0-9]+|$NAME/$NAME#[0-9]+|#[0-9]+)"
KEYWORD='\b(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]]*:?[[:space:]]*'
KEYWORD='(\b(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]]*:?[[:space:]]*|最終工程の後に閉じる[[:space:]]*:[[:space:]]*)'

# **1 件も見つからないことは正常な結果である。** `grep` の終了コードをそのまま返すと、
# 閉じる語の無い Pull Request で失敗したように見える。
Expand Down
Loading
Loading