diff --git a/docs/glossary.md b/docs/glossary.md index 5f3a85aad..f22ee0a7a 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -376,7 +376,7 @@ cross-review / cross-refactoring が参加者の CLI を選び、起動し、監 | モデルを引けない | `model_unavailable` | 担当の CLI が、指定か設定のモデルを使えないと返したこと(参加の確認と起動結果の理由 model_unavailable) | — | — | `docs/specifications/cross-participant-admission-check.md` | | 認証の失効 | `auth_expired` | 認証の状態確認は通るが、更新トークンの失効などで実行のときに認証を作り直せないこと(参加の確認と起動結果の理由 auth_expired) | — | — | `docs/specifications/cross-participant-admission-check.md` | | 既定のモデルへの切り替え | `default_models` | 引数で明示していないモデルを引けない CLI を、既定のモデルで担当に入れること(participants.default_models) | — | — | `docs/specifications/cross-participant-admission-check.md` | -| 相手役 | — | cross-review のレビュー担当、cross-refactoring の提案・実装の担当として、ホストから CLI プロセスで起動されるランタイム(#2231) | — | — | — | +| 相手役 | — | cross-review のレビュー担当、cross-refactoring の提案・実装の担当として、ホストから CLI プロセスで起動されるランタイム(#2231) | — | — | `docs/specifications/ndf-distribution-runtimes.md` | ## NDF の cross-review(`ndf-cross-review`) @@ -584,8 +584,8 @@ release が走らせるリリースの種別・リリースコマンド・公開 | スプリント経由の PR | — | 範囲の PR のうち、merge commit でベースブランチへ入った PR の 2 つ目の親の側(スプリントブランチ)へ merge commit で入った PR。変化と移行の手順はスプリント PR の本文が集めて持つ | — | — | `docs/specifications/ndf-release-approval-included-prs.md` | | 承認の材料 | — | 承認資料が集める 5 つの材料。レビュー(cross-review のラウンド数と見送った指摘)・リファクタリング(採用と取り消しの件数)・全体テスト(コマンド・合否・件数)・設計文書の未確認・未実施のリリース後テスト | — | — | `docs/specifications/ndf-release-approval-materials.md` | | 配布物の変化なし | — | PR の本文の `## 利用者向けの変化` が「無し」(「なし」も同じ)だけを持つこと。承認資料の「含む PR」の行に印を付け、CHANGELOG の版の節と「配る中身」には載せない。節の無い本文(題名で代える)とは別に扱う | — | — | `docs/specifications/ndf-release-approval-included-prs.md` | -| マニフェスト | — | plugins/ndf/manifests/<ランタイム>-skills.txt。ランタイムごとに配る Skill の一覧で、配布の唯一の基準(#2231) | — | — | — | -| 配布先のランタイム | — | マーケットプレイスのプラグインを導入できる形で届けるランタイム。#2231 の後は Claude Code と codex で、相手役のランタイムとは別に決まる(#2231) | — | — | — | +| マニフェスト | — | plugins/ndf/manifests/<ランタイム>-skills.txt。ランタイムごとに配る Skill の一覧で、配布の唯一の基準(#2231) | — | — | `docs/specifications/ndf-distribution-runtimes.md` | +| 配布先のランタイム | — | マーケットプレイスのプラグインを導入できる形で届けるランタイム。#2231 の後は Claude Code と codex で、相手役のランタイムとは別に決まる(#2231) | — | — | `docs/specifications/ndf-distribution-runtimes.md` | ## NDF の指示書チェック(`ndf-instructions`) diff --git a/docs/glossary/glossary.json b/docs/glossary/glossary.json index 845c3ce4e..cc5007acb 100644 --- a/docs/glossary/glossary.json +++ b/docs/glossary/glossary.json @@ -4691,19 +4691,19 @@ "term": "相手役", "context": "ndf-agent-cli", "meaning": "cross-review のレビュー担当、cross-refactoring の提案・実装の担当として、ホストから CLI プロセスで起動されるランタイム(#2231)", - "pending_source": "issues/issue-2231-requirements.md" + "source": "docs/specifications/ndf-distribution-runtimes.md" }, { "term": "マニフェスト", "context": "ndf-release", "meaning": "plugins/ndf/manifests/<ランタイム>-skills.txt。ランタイムごとに配る Skill の一覧で、配布の唯一の基準(#2231)", - "pending_source": "issues/issue-2231-requirements.md" + "source": "docs/specifications/ndf-distribution-runtimes.md" }, { "term": "配布先のランタイム", "context": "ndf-release", "meaning": "マーケットプレイスのプラグインを導入できる形で届けるランタイム。#2231 の後は Claude Code と codex で、相手役のランタイムとは別に決まる(#2231)", - "pending_source": "issues/issue-2231-design.md" + "source": "docs/specifications/ndf-distribution-runtimes.md" }, { "term": "最終工程の記録", diff --git a/docs/specifications/README.md b/docs/specifications/README.md index 91eb4b67c..2568956e3 100644 --- a/docs/specifications/README.md +++ b/docs/specifications/README.md @@ -112,5 +112,7 @@ | [ndf-supervise-test-limits-from-whole-runs.md](ndf-supervise-test-limits-from-whole-runs.md) | 予算なしのテストの上限を、所要の記録と直近の全体テストの実測(whole.jsonl)の大きい方の 3 倍で決め、テストのステップの開始で決め直すこと | | [ndf-step-result-gaps-and-reading.md](ndf-step-result-gaps-and-reading.md) | 手順のスクリプトの結果 JSON の欠け(`gaps`)・過程(`process`)・判断(`decisions`)と、`ok` を欠けの無いときだけにする検査(`validate_result`・欠けの残る結果の `stopped` / 終了コード 6)、シェルから同じ形を出す `step_result.py emit` と `step-result.sh`、読む側の共通の関数(`step_read.py`)、記録のスクリプト(`progress-record.sh`・`projects-sync.sh`)の返し方と呼ぶ側が止まらずに報告へ載せること、子の 7 件がこの形をどう使ったか。形と終了コードの表は `plugins/ndf/scripts/lib/README.md` が正 | | [ndf-run-state-owner-and-sweep.md](ndf-run-state-owner-and-sweep.md) | 実行をまたいで残る状態(レビュー worktree `pr`・`rf`、セッションの状態ファイル、`ndf-deps.*`、`fix-pr-*`、`ndf-tests-*`、投稿キューの項目)に持ち主と寿命を記録し、終わった実行の残骸を cross-review と cross-refactoring の開始・merged の `cleanup`・テストのセッションの終わりで片付ける理由と境界(`--force` を使わない、未 push のコミットは自分で数える、寿命の窓は 24 時間、生きている持ち主・open の PR・作業の残る worktree・判定できない状態は理由付きで残す、別の実行が使う worktree では開始を止める、今回分でない位置エラーの `review-post` は控えへ外す)、持ち主の記録の形、`sweep_states`・`remove_review_worktree`・`Queue.flush(keep)`/`outcome` の契約。状態の一覧は `lib/run_state_kinds.py` の `KINDS` が正 | +| [ndf-distribution-runtimes.md](ndf-distribution-runtimes.md) | 配布先を Claude Code と Codex に限り、agy・Kiro CLI は cross 系の相手役としてだけ起動すること(#2231)。導入物の不在の検査(`test_distribution_runtimes.py`)、相手役の起動経路が配布物を読まないこと、前の版で入れた手元の扱い。利用者向けの残し方と消し方は `plugins/ndf/README.md` が正 | +| [ndf-sprint-close-final-stage.md](ndf-sprint-close-final-stage.md) | スプリント課題を最終工程の記録(閉じる条件 3・`--final-stage`)を確かめてから閉じること、振り返りの行を記録の PR の最後の配布の記録と比べる基準(`dist_comment_id`)、まとめのプランの並び(retro の後に close)、既定ブランチ宛の Pull Request の closing keywords を閉じる予定の参照へ置き換えること(#2228・#2082・#2119)。手順は `progress-tracking` の「スプリントを閉じる」が正 | Skill の挙動仕様はここに置かない。Skill に関する詳細は対象 Skill の `SKILL.md` を参照する。 diff --git a/docs/specifications/ndf-distribution-runtimes.md b/docs/specifications/ndf-distribution-runtimes.md new file mode 100644 index 000000000..b397ad6bf --- /dev/null +++ b/docs/specifications/ndf-distribution-runtimes.md @@ -0,0 +1,155 @@ +# 配布先は Claude Code と Codex で、agy・Kiro CLI は cross 系の相手役としてだけ起動する + +マーケットプレイスのすべてのプラグイン(ndf・playwright-kit・mcp-* 10 個)を、Claude Code と Codex へすべての Skill で +配る。agy と Kiro CLI へは何も配らず、cross-review / cross-refactoring の相手役として、ホスト(Claude Code・Codex)から +CLI プロセスで起動するだけにする(#2231)。 + +**この文書が配布先の正本である。** 次の確定仕様に残る agy・Kiro CLI への配布・導入物(`dev.agy/`・`dev.kiro/`・ +`agy-skills.txt`・`kiro-skills.txt`)・その生成と検査・スモークの記述は、配布先を 4 つにしていた時点のもので、 +配布先についてはこの文書が優先する。 + +| 確定仕様 | 配布先を 4 つにしていた時点の記述 | +| --- | --- | +| [runtime-plugin-distribution.md](runtime-plugin-distribution.md) | Kiro CLI・agy の名前空間ディレクトリ、manifest、agy のエージェント定義の生成 | +| [runtime-plugin-container-smoke.md](runtime-plugin-container-smoke.md) | Kiro の像・adapter・確認 | +| [ndf-knowledge-and-kiro.md](ndf-knowledge-and-kiro.md) | Kiro CLI の導入(installer・symlink・steering) | + +## 概要 + +| ランタイム | 役割 | 届けるもの | +| --- | --- | --- | +| Claude Code | 配布先・ホスト | すべてのプラグイン。NDF は `plugins/ndf/manifests/claude-skills.txt` の Skill | +| Codex | 配布先・ホスト | すべてのプラグイン。NDF は `plugins/ndf/manifests/codex-skills.txt` の Skill | +| agy | 相手役 | 何も配らない | +| Kiro CLI | 相手役 | 何も配らない | + +agy・Kiro CLI のためだけに保っていた導入物・その生成と検査・スモークテスト・リリース後の導入の確認を外し、 +agy・Kiro CLI だけで起きる不具合(Skill の本文の切り詰めなど)の置き場を無くした。相手役の起動経路は配布物を +読まないため、配布を止めても相手役の振る舞いは変わらない。 + +## 用語 + +配布先のランタイム・相手役・マニフェスト・ホストの定義は、用語集([docs/glossary.md](../glossary.md))にある。 + +## 背景 + +利用者の指示(2026-10-31)は「claude と codex のみ、すべての plugin を配布する。agy、kiro は配布せず、cross 系で +呼ばれるだけ」である。agy・Kiro CLI へ cross 系をホストとして回せる Skill だけを配る案は採らない。ホストとしての +使い方を残さないため、相手役に要る Skill は 0 本になる。マニフェストを空のファイルにして導入物の枠を残す案も +採らない。中身の無い導入物のために生成・検査・スモークを保つことになる。 + +この変更は配布物の取得元を変える操作(プロジェクト MVV の P1)に当たり、承認ゲート 1 の指示と承認ゲート 2 の承認で行った。 + +## 仕様 + +### 常に成り立つ条件 + +| # | 条件 | 破れたときの扱い | +| --- | --- | --- | +| I1 | どのプラグインにも `manifests/agy-skills.txt`・`manifests/kiro-skills.txt`・`dev.agy/`・`dev.kiro/` が無く、`.ndf/supervise.json` の `release.runtimes` は `claude`・`codex` の部分集合である | `scripts/tests/test_distribution_runtimes.py` が落ちる | +| I2 | Claude Code と Codex の配布物(両マニフェスト・各 `.codex-plugin/plugin.json`・`plugins/ndf/hooks/codex.json`・codex 向けの生成物)は配布先を絞った前と同じである | `build-runtime-plugins.sh --check`・`validate-runtime-plugins.sh`・既存の pytest | +| I3 | agy・Kiro CLI を相手役にする起動(`plugins/ndf/scripts/lib/launch-cli.sh` の `agy` / `kiro` の分岐、`cross-refactoring/scripts/prepare-worktrees.sh` の手順書の写し先)は配布先と関わらずに動く | 起動の既存の pytest | +| I4 | 前の版で Kiro CLI へ入れた手元の hook が呼ぶ共通のスクリプト(`plugins/ndf/scripts/hook.py` の `--runtime kiro`・`worktree-guard.sh`・`worktree-session.sh`・`wait-notify.py`)が残る | `worktree/tests/test_guard.py` の Kiro の入力のテスト | +| I5 | ワークフローのジョブと ruleset の必須のチェックが一致する | `required-checks-check`(`scripts/check-required-checks.py`) | + +### 相手役として起動されるとき + +```mermaid +sequenceDiagram + participant H as ホスト(Claude Code / Codex) + participant P as 準備(prepare-worktrees.sh) + participant L as 起動の共通スクリプト(launch-cli.sh) + participant R as 相手役(agy・Kiro CLI) + H->>P: cross-refactoring の初期化 + P->>P: ホストの導入先から REQUIRED_SKILLS を担当の worktree へ写す + H->>L: 依頼文と worktree を渡す + L->>R: CLI プロセスで起動(--agent もプラグインの導入先も指さない) + R->>R: 依頼文と worktree の中の手順書だけを読む + R-->>H: 結果ファイル +``` + +- cross-review のレビュー担当の依頼文は Skill を読まずに完結する(`cross-review/scripts/launch-reviewer.sh` の `render_review_prompt`) +- cross-refactoring は `REQUIRED_SKILLS`(`refactoring`・`tdd-cycle`・`quality-gates`)を**ホストの導入先**から担当の worktree + (Kiro CLI は `.kiro/skills`、agy は `.agents/skills`)へ写す +- 起動の形の正本は `plugins/ndf/skills/external-ai/references/cli-kiro.md`・`cli-agy.md` にある。相手役に使えるかは + `.ndf/runtimes.json` と各 CLI の認証で決まる。cross-review の既定の参加者(claude・codex・kiro とホスト、agy は `--include agy`)は変わらない + +### 配布物を組み立てて確かめる流れ + +```mermaid +graph LR + M[claude・codex のマニフェスト] --> B[build-runtime-plugins.sh] + B --> C[codex の openai.yaml と mcp-* の .codex-plugin] + C --> V[validate-runtime-plugins.sh] + D[test_distribution_runtimes.py] --> V + C --> S[スモーク claude・codex] + R[release.runtimes claude・codex] --> VI[release-verification-steps.py verify-install] +``` + +## データ・設定 + +| 置き場 | 値 | +| --- | --- | +| `plugins/ndf/manifests/` | `claude-skills.txt`・`codex-skills.txt` だけ(行数は manifests が持つ) | +| `plugins/playwright-kit/manifests/` | `claude-skills.txt`・`codex-skills.txt` だけ | +| `.ndf/supervise.json` の `release.runtimes` | `["claude", "codex"]` | +| `.ndf/pace.json` の `verify` | `release-verification-steps.py verify-install --ref develop --runtimes claude,codex` | +| `release-verification-steps.py` の `--runtimes` | 既定 `claude,codex` | +| `.ndf/project.json` の `required_checks` | スモークは `runtime-smoke (claude)`・`runtime-smoke (codex)` | +| `.github/workflows/runtime-plugin-smoke.yml` の matrix | `runtime: [claude, codex]`。`runtime-plugin-authenticated-smoke.yml` の選択肢も `all`・`claude`・`codex` | +| `tests/runtime-smoke/` | `Containerfile.{base,claude,codex}`・`adapters/{claude,codex}.sh` | + +`.ndf/worktree.json` の `.kiro/`(相手役の設定を置く場所)と、`scripts/token-usage.py` の kiro・agy の使用量の読み取り +(相手役の使用量)は相手役の経路として残る。 + +## 運用 + +### 前の版で agy・Kiro CLI へ入れた利用者の手元 + +こちらから手元を消す操作はしない(共通原則 C6)。最後に配った版は v10.27.4 である。残し方と消し方の正本は +`plugins/ndf/README.md` の「agy・Kiro CLI への配布の終了」にある。 + +| ランタイム | 配布を止めた後 | +| --- | --- | +| agy | 導入の写し(`~/.gemini/config/plugins/ndf/`)の絶対パスを指すため、そのまま動く。新しい版は届かない | +| Kiro CLI | `.kiro/agents/ndf.json` の hook は clone の共通のスクリプトを呼び、それが残る(I4)ため、clone を進めても動く。installer は無くなる | + +共通のスクリプトの Kiro の分岐は消さない。消すと clone を進めた Kiro CLI の利用者で、プロンプトを送るたびに hook が失敗する。 +いつ消すかは棚卸しで利用の実態を見て決める。 + +### 範囲の外に残したもの + +Claude Code・Codex へ配る Skill の本文とスクリプトに残る、ホストとしての Kiro CLI・agy の分岐(例: `plugins/mcp/mcp-redash/scripts/redash-mcp-config.js` +の `syncKiroAgent`、cross-review の `docs/01-state-and-review.md` のホストの導入先の候補)は消していない。相手役としての記述 +(担当の worktree の `.kiro/skills`・`.agents/skills`)と同じファイルに並び、取り違えると相手役の経路を壊すためである。 +棚卸しで扱う。 + +`KIRO.md` は指示書のチェック(`.ndf/instructions.json`)が読む指示書として残し、相手役としての Kiro CLI の説明だけを持つ。 + +### 確かめていないこと + +| 項目 | 内容 | +| --- | --- | +| プロジェクト MVV との食い違い | Mission は 4 つのランタイムを挙げる。改訂は #2296 で扱う | +| 相手役が配布を止めた後も同じ結果を返すか | 起動の経路をコードで読んで判断した。実物はリリース後テストで確かめる | + +## テスト観点 + +- `scripts/tests/test_distribution_runtimes.py` が、`plugins/` の下の agy・Kiro CLI の導入物とマニフェストの不在と、 + `release.runtimes` が `claude`・`codex` に収まることを確かめること。`plugins/mcp/mcp-notion/dev.kiro/` を 1 つ戻すと落ち、 + `release.runtimes` に `kiro` を足すと落ちること +- `build-runtime-plugins.sh --check`・`validate-runtime-plugins.sh` が agy・Kiro CLI の生成物を求めずに通ること +- Codex のマニフェスト・`.codex-plugin`・`hooks/codex.json` が配布先を絞った前と同じであること +- 相手役の起動の pytest(`test_lib_launch_cli_runtimes.py`・`cross-review/tests/test_launch_cli_runtimes.py`・`test_launch_agy.py`・ + `cross-refactoring/tests/test_launch_agy_phases.py`・`test_prepare_worktrees.py`)が通ること +- `worktree/tests/test_guard.py` の Kiro の入力のテストが通ること +- スモークの matrix が `[claude, codex]` で通り、`required-checks-check` が通ること +- リリース後に、新しい版を入れた環境から `/ndf:cross-review --include agy` と `/ndf:cross-refactoring ` を回し、 + agy・Kiro CLI の結果ファイルが揃うこと + +## 関連リンク + +- [runtime-plugin-distribution.md](runtime-plugin-distribution.md): Claude Code・Codex の配布の形 +- [cross-review-participants-and-seats.md](cross-review-participants-and-seats.md): 参加者プール +- [docs/versioning-and-distribution.md](../versioning-and-distribution.md): 版と配布の正本 +- #2231 diff --git a/docs/specifications/ndf-knowledge-and-kiro.md b/docs/specifications/ndf-knowledge-and-kiro.md index 4213f4f39..c6149dcf2 100644 --- a/docs/specifications/ndf-knowledge-and-kiro.md +++ b/docs/specifications/ndf-knowledge-and-kiro.md @@ -1,5 +1,7 @@ # NDF 知識構造・Kiro CLI 仕様 +> **配布先は Claude Code と Codex である(#2231)。** この文書に残る agy・Kiro CLI への配布・導入物・生成・検査・スモークの記述は配布先を 4 つにしていた時点のもので、配布先については [ndf-distribution-runtimes.md](ndf-distribution-runtimes.md) が優先する。 + ## 概要 NDF の知識配置(`AGENTS.md` と版と配布の正本、README の役割を含む)、Serena MCP 分離、Kiro CLI 対応に関する確定仕様。 diff --git a/docs/specifications/ndf-sprint-close-final-stage.md b/docs/specifications/ndf-sprint-close-final-stage.md new file mode 100644 index 000000000..f4d3b0fc3 --- /dev/null +++ b/docs/specifications/ndf-sprint-close-final-stage.md @@ -0,0 +1,266 @@ +# スプリント課題を最終工程の記録を確かめてから閉じ、既定ブランチ宛の Pull Request のマージでは閉じない + +NDF のどの経路で閉じても、閉じた課題はその実行の最終工程の記録を持つ。`sprint-close.py` が課題ごとに +最終工程の記録(閉じる条件 3)を確かめ、まとめのプランは振り返りの後に課題を閉じ、既定ブランチ宛の +Pull Request の本文には GitHub がマージで課題を閉じる closing keywords を残さない(#2228。子の #2082・#2119 を含む)。 + +**手順は各 Skill の `SKILL.md` が正である。** 閉じる条件の表・呼ぶ Skill と `--final-stage` の値の対応・ +プランの並びの正本は `plugins/ndf/skills/progress-tracking/SKILL.md` の「スプリントを閉じる」にあり、 +ここへ書き写さない。この文書は、決めたことの理由と、書く側と読む側が共有する形を残す。 + +| 何を読むか | 正本 | +| --- | --- | +| 閉じる条件 1〜3・呼ぶ側と `--final-stage` の値・まとめのプランの並び | `plugins/ndf/skills/progress-tracking/SKILL.md` の「スプリントを閉じる」 | +| closing keywords を本文だけに書くことと、既定ブランチ宛での置き換え | `plugins/ndf/skills/pr/SKILL.md` | +| 後片付けの止まり方・閉じる条件 1・2 の理由・リリース記録の形 | [ndf-cleanup-and-bundle-closing.md](ndf-cleanup-and-bundle-closing.md) | + +## 概要 + +閉じる経路は 3 つあり、変更前はどれも工程の通過を見なかった。 + +| 経路 | 変更前に起きたこと | 今の扱い | +| --- | --- | --- | +| GitHub が既定ブランチへのマージで本文の closing keywords の課題を閉じる | volareinc/carmo-screening の PR 344 の `Closes #342` で、受け入れ条件 11 件が未チェックのまま閉じた(#2082) | 既定ブランチ宛の本文を NDF の手順で書くとき、closing keywords を閉じる予定の参照へ置き換える | +| `sprint-close.py` をプラン・conductor・Skill のどれかが打つ | s2086 で #2086 がリリース後テストの前に閉じ、不合格の条件を持ったまま閉じて残った(#2119) | `sprint-close.py` が最終工程の記録を確かめ、無ければ閉じない | +| ボードの `Done` でボードの自動化が閉じる | 上の経路の中の 1 手 | 判定を通った課題だけ `Done` にする(変わらない) | + +閉じる時点の決まりは `progress-tracking` の 1 か所、判定は `sprint-close.py`(と `sprint_close_lib/`)の 1 か所、 +閉じる指定の形は `lib/closing.py` の 1 か所に置く。まとめのプランと Skill の本文は `--final-stage` の値を渡すだけで、 +閉じてよいかを判定しない。 + +## 用語 + +最終工程・最終工程の記録・閉じる予定の参照・スプリント課題・closing keywords・参照だけの課題の定義は、 +用語集([docs/glossary.md](../glossary.md))にある。 + +## 構成要素 + +| 要素 | 責務 | +| --- | --- | +| `plugins/ndf/scripts/sprint-close.py` | 引数 `--final-stage` を受け、課題ごとに閉じる条件 1〜3 を判定して閉じる | +| `plugins/ndf/scripts/sprint_close_lib/final_stage.py` | 閉じる条件 3 の判定 `final_stage_gap(stage, body, since)` と、満たさない課題の項目 `gap_item` | +| `plugins/ndf/scripts/lib/dist_record.py` | `parse_record(text, parts)` が、最後の配布の記録のコメントの識別子 `dist_comment_id` を返す | +| `plugins/ndf/scripts/sprint_close_lib/collect.py` | `read_record` が記録の PR を 1 回読み、本文とコメントを連結した文字列と部分ごとの(先頭の行の番号, コメントの識別子)を返す | +| `plugins/ndf/scripts/lib/closing.py` | 閉じる予定の参照の語 `DEFERRED`(`最終工程の後に閉じる`)、置き換え `defer_closing`、2 つの形を読む `closing_issues` / `closing_refs` / `closing_numbers`、closing keywords だけを読む `closing_words` | +| `plugins/ndf/scripts/lib/closing-issues.sh` | シェルの読み手。閉じる予定の参照も取り出す。出力の形(`<リポジトリ>\t<番号>`)は変わらない | +| `plugins/ndf/scripts/lib/repo.py` | `merge_closes_issues(root, base)`(宛先のマージで GitHub が閉じるか)と `defer_for_base(root, base, text)`(当たるときだけ `defer_closing` に通す) | +| `plugins/ndf/scripts/pr-steps.py`・`plugins/ndf/scripts/supervise_lib/pr.py` | 本文を送る前に `defer_for_base` を通す | +| `plugins/ndf/scripts/supervise_lib/sprint.py`・`sprint_close_steps.py`・`release_templates.py` | まとめのプランを `merge →(release-verify)→ retro → close → refine` の順に組む | + +```mermaid +graph LR + subgraph 書く側 + PRS[pr-steps.py] --> DFB[lib/repo.py defer_for_base] + PLPR[supervise_lib/pr.py] --> DFB + DFB --> MCI[merge_closes_issues] + DFB --> DEF[lib/closing.py defer_closing] + end + subgraph 読む側 + SC[sprint-close.py] --> CIS[lib/closing-issues.sh] + MRG[merged・hook] --> CIS + REL[release_lib] --> CPY[lib/closing.py closing_refs] + SC --> FS[sprint_close_lib/final_stage.py] + end + subgraph まとめのプラン + RV[release-verify] --> RT[retro] --> CL[close] --> RF[refine] + end + CL --> SC +``` + +## 仕様 + +### 常に成り立つ条件 + +| # | 条件 | 破れたときの扱い | +| --- | --- | --- | +| I1 | 課題を閉じてボードを `Done` にするのは、その課題のその実行の最終工程の記録があるときだけである。振り返りの行は、前の実行のものを数えない | 閉じない。`kept_open`(既に閉じていれば `closed_unverified`)と、通っていない工程の名前を含む `reason` で返す | +| I2 | 最終工程の記録を読む置き場(課題の本文)を読めないとき、記録があるとは読まない | 閉じない。`failed` と打ち直しの `cmd`、`status: stopped`(終了コード 1) | +| I3 | `--final-stage` を省いたときの最終工程は `振り返り`(最も後ろ)である。省いても閉じる条件は緩まない | — | +| I4 | 最終工程が `リリース後テスト` のとき、閉じる条件 2 を `--with-verification` の有無にかかわらず見る | 閉じない | +| I5 | `--record-pr 0`(本番の記録なし)と `--record-pr unknown` の扱いは条件 3 の前と変わらない。`unknown` は本文を読まずにすべて `kept_open` で返す | — | +| I6 | まとめのプランの `next` のつながりで、`close` は `retro` の後、`refine` の前にある。`retro` と `release-verify` の指示は課題を閉じない。`close` は `--final-stage 振り返り` を明示して渡す | プランを組む関数のテストで落ちる | +| I7 | 宛先が既定ブランチ(既定ブランチか宛先を決められないときを含む)の Pull Request を NDF の手順で書くと、本文に closing keywords が残らず、置き換えた指し先は同じ課題を指す閉じる予定の参照になる | — | +| I8 | 宛先が既定ブランチでない Pull Request の本文は書き換えない | — | +| I9 | 閉じる予定の参照は closing keywords を含まない | `closing_words` が一致を返したらテストで落ちる | +| I10 | スプリント課題は closing keywords・閉じる予定の参照・`--issues` の和であり、閉じる予定の参照が指す課題を参照だけの課題にしない | — | + +### `sprint-close.py` の入出力 + +```text +sprint-close.py --record-pr [--final-stage 配布|リリース後テスト|振り返り] + [--prs 1,2] [--issues 3,4] [--with-verification] [--label …] [--dry-run] [--root ] [--repo ] +``` + +| 項目 | 値 | +| --- | --- | +| `--final-stage` | 3 つの値のどれか。省けば `振り返り`。それ以外は呼び出しの誤り(終了コード 3) | +| 条件 3 を満たさない課題 | `result: kept_open`・`reason: 最終工程(<工程>)の記録が無い: <何が無いか>`。既に閉じていれば `closed_unverified`(`閉じているが閉じる条件 3 を満たさない: …`。開き直さない) | +| 課題の本文を読めない | `result: failed`・同じ呼び出しの `cmd`。`status: stopped`・終了コード 1 | +| `metrics.final_stage` | 判定に使った最終工程 | +| `decisions` | `{"decision": "最終工程を <工程> として判定した", "basis": "--final-stage <値>(省略時は振り返り)"}` を 1 件 | +| 終了コード | 0 / 1 / 2 / 3 の意味は条件 3 の前と同じ | + +最終工程ごとの記録と読む置き場: + +| 最終工程 | 最終工程の記録 | 読む置き場 | +| --- | --- | --- | +| `配布` | 閉じる条件 1(最後の配布の記録の `段階:` が `本番` か `配布なし`。`--record-pr 0` は満たす) | 記録の PR | +| `リリース後テスト` | 閉じる条件 2(`--with-verification` を付けたのと同じ判定) | 記録の PR | +| `振り返り` | 課題の本文に、行頭から `振り返り: https://github.com/<所有者>/<リポジトリ>/(issues|pull)/<番号>#issuecomment-<識別子>` の行があり、そのうち最大の `<識別子>` が比べる基準(`dist_comment_id`)以上である | 課題の本文と記録の PR | + +`振り返り` で満たさないときの `<何が無いか>` は 3 つである。 + +| 状態 | `<何が無いか>` | +| --- | --- | +| 比べる基準が `None` | `比べる配布の記録のコメントが無い` | +| 行が 1 つも無い | `課題の本文に振り返りの記録の行が無い` | +| 行の識別子がすべて基準より小さい | `課題の本文の振り返りの行が今回の配布の記録より前のもの` | + +### 比べる基準(`dist_comment_id`) + +振り返りの行は課題の本文に残り続ける。前のスプリントで振り返りを通り、開いたまま持ち越した課題が、 +今回の振り返りの前に条件 3 を満たさないよう、行が指すコメントの識別子を記録の PR の最後の配布の記録と比べる。 + +| 最後の配布の記録の置き場 | 基準 | +| --- | --- | +| 記録の PR のコメント | そのコメントの識別子(`comments[].url` の `#issuecomment-<識別子>` の数字) | +| 記録の PR の本文 | 記録の PR の最初のコメントの識別子。コメントが 1 件も無ければ `None` | +| `--record-pr 0` | `0`(`NO_BASE`。配布の記録が無いため、行があれば満たす) | + +比べ方は「以上」である。本文にある記録で、今回の振り返りを記録の PR の最初のコメントとして投稿したとき、 +その識別子が基準と等しくなるためである。記録の PR は条件 1 と同じ 1 回の `gh pr view --json body,comments` で読み、 +`gh` の呼び出しを増やさない。 + +### 課題 1 件の判定の流れ + +```mermaid +flowchart TD + A[課題 1 件] --> B{record-pr が unknown か
条件 1 を満たさない} + B -->|当たる| K1[kept_open] + B -->|当たらない| C{条件 2 を見るか
with-verification
または最終工程がリリース後テスト} + C -->|見る| D[錠の中で状態と本文を 1 回読む] + C -->|見ない| E[最終工程が振り返りなら
状態と本文を 1 回読む] + D -->|読めない| F[failed] + E -->|読めない| F + D --> G{条件 2} + G -->|満たさない| K2[kept_open / closed_unverified] + G -->|満たす| H + E --> H{条件 3
final_stage_gap} + H -->|記録が無い| K3[kept_open / closed_unverified] + H -->|記録がある| I[受け入れ条件の印 → ボード Done → 閉じる → 読み直す] +``` + +条件 3 は条件 2 と同じ 1 回の本文の読みを使う。印を書くのは条件 3 も満たしたときだけで、満たさない課題の +本文は書かない。`--dry-run` は判定まで行い、書かない。 + +### まとめのプランの並び + +```mermaid +flowchart LR + M[merge] -->|配布の記録あり| RV[release-verify
課題を閉じない] + M -->|配布の記録なし| RT + RV --> RT[retro
課題を閉じない] + RT --> CL[close
sprint-close.py --final-stage 振り返り --with-verification] + CL -->|0 で終わったときだけ| RF[refine] +``` + +まとめのプランはどのモードでも `retro` を持つため、プランの中の最終工程はどのモードでも振り返りになる。 +`配布` と `リリース後テスト` は、プランの外で最終工程を担う Skill(`light` の `release`、振り返りを通らない +`operation` の `release-verification` か `release`)だけが渡す。 + +### 閉じる予定の参照と本文の置き換え + +```text +最終工程の後に閉じる: <指し先> +``` + +`<指し先>` は closing keywords と同じ 3 つ(`#<番号>`・`<所有者>/<リポジトリ>#<番号>`・課題の URL)。`:` の前後の +空白は 0 個以上を許す。1 つの指し先に 1 つ書く。 + +置き換えるかは Pull Request の宛先(新しく作るなら `--base` か起点、既存なら `baseRefName`)で決める。 +`merge_closes_issues` は、既定ブランチ(`default_branch`)を決められない・宛先が分からない・宛先が既定ブランチ +(`origin/` を外して比べる)のときに真を返す。 + +`pr-steps.py create` / `update` の結果: + +| 項目 | 値 | +| --- | --- | +| 本文 | 当たれば `Closes #12` などを `最終工程の後に閉じる: #12` へ置き換えてから送る。指し先の字面は変えない | +| `metrics.deferred_closing` | 置き換えた指し先の字面の配列(置き換えなければ空) | +| `items` | 置き換えた指し先ごとに `{"kind": "closing", "name": "<指し先>", "result": "deferred"}` | +| `metrics.closing_issues_in_body` | 2 つの形の指し先をどちらも載せる | +| `status` | 置き換えは `ok` のまま(欠けではない) | + +プランの pr のステップ(`supervise_lib/pr.py`)も同じ判定で置き換え、置き換えた指し先をステップの状態の +`deferred_closing` に残す。 + +## 決定の理由 + +- **最終工程の記録は GitHub に残った記録から読む。** 配布の記録・リリース後テストの行・課題の本文の振り返りの行は + どれも GitHub にあり、conductor・supervisor・別の機械のどこから打っても同じものを読む。プランの状態ディレクトリと + 通過記録は手元のファイルで、別の機械や手打ちの経路からは読めない。振り返りの行は記録の PR ではなく課題の本文から + 読む(#2086 の行は記録の PR と違う PR を指していた) +- **最終工程は引数で受け、省けば振り返りにする。** 課題の本文の `モード:` は実例でどれも `—` で、最終工程を導けない。 + 省いたときに最も厳しい値になるため、呼ぶ側の書き違いで閉じる条件が緩まない +- **`--final-stage リリース後テスト` は条件 2 を必ず見る。** 2 つの引数を別々に必須にすると、片方の付け忘れで + 最終工程を確かめずに閉じる経路が残る +- **前の版で工程を通った課題のための移行の手段を作らない。** 振り返りを通った課題はすでに本文に行を持つ。 + 判定を飛ばす引数を足すと、新しい経路でも判定を飛ばす手段になる。行を持たない課題は `kept_open` で残り、 + `next` が「振り返りを通すか、確かめて手で閉じる」を示す +- **既定ブランチ宛の closing keywords は止めずに置き換える。** プランの pr のステップは本文を機械で組むため、 + 止めると既定ブランチを起点にするリポジトリでスプリントのたびに無人の実行が止まる。置き換えは宛先で決める。 + GitHub が閉じるかを決めるのは各 Pull Request の宛先であり、起点の設定ではない +- **閉じる予定の参照は専用の形にする。** `Refs #N` は参照だけの課題の意味と衝突する。`NDF-Closes` のような造語は + 語の境界の後に `Closes` が来て closing keywords として一致する。`--issues` だけで集めると、付け忘れで閉じる課題が + 0 件になる +- **振り返りの行は形だけを見て、指すコメントは読まない。** コメントを読むと課題ごとに `gh` の呼び出しが 1 回増える。 + 行は `retrospective` が投稿の後にだけ書く +- **プランで閉じるのは `close` だけにし、Skill からの呼び出しも残す。** プランを通らない実行にも閉じる担い手が要る。 + 判定は `sprint-close.py` が行うため、両方が打っても早すぎる時点では閉じず、2 度目は `already_closed` になる。 + プランの `retro` に閉じさせないのは、担当が `--with-verification` を省くと条件 2 を見ずに閉じるためである + +## 運用 + +- 振り返りを通らずに開いたまま残った課題は、振り返りを通すか、確かめて手で閉じる(手で `gh issue close` を打つ + 経路は NDF の判定の外) +- GitHub の画面で本文を書き直したときは置き換えない(NDF の手順を通らない書き込み) + +### 確かめていないこと + +| 項目 | 内容 | +| --- | --- | +| コメントの識別子の大小と投稿の順 | 識別子が投稿の順に大きくなることに頼る(#2086 と記録の PR 2109 の 1 組で確かめた)。順に並ばない例が出たら投稿時刻の比較へ替える | +| 配布の記録が本文だけにある記録の PR | 最初のコメントを基準にする。コメントの無い記録の PR では、振り返りを最終工程とする課題が閉じない(安全側)。実例は確かめていない | +| `--record-pr 0` の前の実行の行 | 比べる基準が無く、前のスプリントの行を持つ持ち越しの課題は、その実行の振り返りの前に条件 3 を満たしうる | +| 振り返りの行の中身 | 行の URL のコメントが実在するかは読まない | +| `--with-verification` を省いた振り返りの経路 | 条件 2 を見ずに閉じうる(#2293) | + +## テスト観点 + +テストは `plugins/ndf/scripts/tests/` の `test_sprint_close_final_stage.py`・`test_closing.py`・`test_supervise_pr_closing.py`・ +`test_sprint_close_issues.py`・`test_sprint_close_references.py` ほかにある。 + +- 本文に振り返りの行が無い課題は、`--final-stage` を省いて打つと `--with-verification` の有無の両方で `kept_open` と + 「振り返り」を含む `reason` が返り、閉じる・ボードを書く `gh` の呼び出しが無いこと +- 振り返りの行の識別子が最後の配布の記録のコメントの識別子より小さい課題は閉じず、大きい行を足すと閉じること +- 最後の配布の記録がコメントにあればその識別子、本文にあれば最初のコメントの識別子、コメントが無ければ `None` が + 基準になり、`None` では閉じないこと。基準と等しい識別子を数えること。記録の PR を読む `gh` の呼び出しが 1 回であること +- 課題の本文の読みが失敗すると `failed`・`status: stopped`・終了コード 1 になること +- 行がすべて合格で振り返りの行がある課題で、印・`Done`・閉じるが同じ順で起きること。`--record-pr 0` で行があれば閉じ、 + `unknown` では本文を読まずにすべて `kept_open` になること +- `--final-stage リリース後テスト` で `--with-verification` を付けずに打つと、不合格の行を持つ課題が閉じないこと +- まとめのプランの `next` をたどった並びが `release-verify → retro → close → refine`(記録なしでは `retro → close → refine`)で、 + どのモードでも `close` が `retro` の後、`refine` の前にあること +- 既定ブランチと起点が同じ一時のリポジトリで `pr-steps.py create` / `update` と `supervise_lib/pr.py` の `_publish` が + `gh` に渡す本文に closing keywords が無く、閉じる予定の参照が同じ指し先で残ること。既定ブランチを決められない構成でも + 同じであること +- 閉じる予定の参照だけを持つ Pull Request で `sprint-close.py --prs <番号> --dry-run` を打つと、その課題が閉じる対象として + 判定され、参照だけの課題にも終了コード 2 にもならないこと。`closing-issues.sh` と `closing.closing_refs` が同じ本文から + 同じ指し先を返すこと +- 宛先が既定ブランチでない構成(`develop` 宛)では本文が書き換わらないこと + +## 関連リンク + +- [ndf-cleanup-and-bundle-closing.md](ndf-cleanup-and-bundle-closing.md): 閉じる条件 1・2 と後片付け +- [docs/glossary.md](../glossary.md): 用語集 +- #2228・#2082・#2119 diff --git a/docs/specifications/runtime-plugin-container-smoke.md b/docs/specifications/runtime-plugin-container-smoke.md index 274638d06..be8d359b6 100644 --- a/docs/specifications/runtime-plugin-container-smoke.md +++ b/docs/specifications/runtime-plugin-container-smoke.md @@ -1,5 +1,7 @@ # Runtime Plugin Container Smoke Test 仕様 +> **配布先は Claude Code と Codex である(#2231)。** この文書に残る agy・Kiro CLI への配布・導入物・生成・検査・スモークの記述は配布先を 4 つにしていた時点のもので、配布先については [ndf-distribution-runtimes.md](ndf-distribution-runtimes.md) が優先する。 + ## 概要 runtime 分離後の Claude Code / Codex / Kiro 向け plugin 配布物を、ホスト環境を汚染しない Docker コンテナ内で smoke test する仕様。 diff --git a/docs/specifications/runtime-plugin-distribution.md b/docs/specifications/runtime-plugin-distribution.md index 1719a1ef7..22dc864c2 100644 --- a/docs/specifications/runtime-plugin-distribution.md +++ b/docs/specifications/runtime-plugin-distribution.md @@ -1,5 +1,7 @@ # Runtime Plugin Distribution 仕様 +> **配布先は Claude Code と Codex である(#2231)。** この文書に残る agy・Kiro CLI への配布・導入物・生成・検査・スモークの記述は配布先を 4 つにしていた時点のもので、配布先については [ndf-distribution-runtimes.md](ndf-distribution-runtimes.md) が優先する。 + ## 概要 AI Plugins marketplace は、Claude Code / Codex / Kiro CLI / agy へ同じ plugin を配布する。 diff --git a/issues/issue-2228-design-decisions.md b/issues/issue-2228-design-decisions.md deleted file mode 100644 index 52e51fd50..000000000 --- a/issues/issue-2228-design-decisions.md +++ /dev/null @@ -1,89 +0,0 @@ -# #2228 の設計: 決定の記録 - -設計文書の本体は [issue-2228-design.md](issue-2228-design.md) にある。要求の未決 1〜4 は決定 1・4・5・6・8 で決める。 - -## 決定の記録 - -### 決定 1: 別の機械とセッションからも同じ判定になるよう、最終工程の記録は GitHub に残った記録から読む - -判定の材料は、配布の記録(`段階:`)・リリース後テストの行・課題の本文の `振り返り: <コメントの URL>` の行の 3 つにする(要求の未決 1 の候補 (b))。どれも GitHub にあり、conductor・supervisor・別の機械のどこから打っても同じものを読む。配布とリリース後テストは今の閉じる条件 1・2 がすでに読んでおり、足すのは振り返りの行だけになる。 - -振り返りの行は、`retrospective` の「辿る経路を作る」がすでに課題ごとに書いている(#2086・#2216・#2227・#2229 で確かめた)。記録の PR のコメントは読まない。#2086 の行は記録の PR(2109)と違う PR(2110)を指しており、記録の PR から探すと見落とす。 - -#2227 の結果 JSON(候補 (a))は採らない。プランの状態ディレクトリは手元の一時の置き場で、conductor が手で打つ経路では存在しない。通過記録に「工程を出た」記録を足す案(候補 (c))も採らない。通過記録はリポジトリの外の手元のファイルで、別の機械からは読めない。 - -根拠: Value 5 / Value 6 / Vision(MVV 版 3) - -### 決定 2: 呼ぶ側の書き違いで閉じる条件が緩まないよう、最終工程は引数で受け、省けば振り返りにする - -`sprint-close.py` に `--final-stage 配布|リリース後テスト|振り返り` を足し、省いたときは最も後ろの `振り返り` として判定する。s2086 のように conductor が手で打つ経路では、何も付けなければ振り返りの記録が要る。緩めるには、最終工程を担う Skill(`release`・`release-verification`)がその値を明示する必要がある。どの Skill がどの値を渡すかは `progress-tracking` の「スプリントを閉じる」の呼ぶ Skill の表が持つ。 - -課題の本文の `## 進行` の `モード:` から最終工程を導く案は採らない。実際の課題(#2086・#2172・#2216・#2227・#2229)ではどれも `—` で、導けない。工程表(`WF_STAGE_MATRIX`)を Python から読む部品を新しく作っても、`operation` は経路でリリース後テストと振り返りの有無が変わり、モードだけでは決まらない。 - -根拠: Value 2 / Value 4(MVV 版 3) - -### 決定 3: 最終工程がリリース後テストの経路で条件 2 を見落とさないよう、その値は条件 2 を必ず見る - -`--final-stage リリース後テスト` を渡したときは、`--with-verification` を付けなくても閉じる条件 2 を判定する。この経路の最終工程の記録はリリース後テストの行そのものであり、条件 2 を見ずに閉じると最終工程の記録を確かめないまま閉じる。 - -2 つの引数を別々に必須にする案は採らない。片方を付け忘れると、最終工程を確かめずに閉じる経路が残る。 - -根拠: Value 6(MVV 版 3) - -### 決定 4: 前の版で工程を通った課題のために移行の手段を作らない - -この版より前に振り返りを通った課題は、すでに本文に振り返りの行を持つ(決定 1)。行を持たずに開いている課題は `kept_open` で残り、`reason` と `next` が「振り返りを通すか、確かめて手で閉じる」を示す(要求の未決 2)。 - -古い課題を一度だけ閉じる引数(判定を飛ばす `--force` の類)は足さない。足すと、新しい経路でも判定を飛ばす手段として使える。手で `gh issue close` を打つ経路は要求の対象範囲の外にあり、すでにある。 - -根拠: Value 1 / Value 6(MVV 版 3) - -### 決定 5: 無人の実行を止めずにマージで閉じなくするため、既定ブランチ宛の本文の closing keywords は止めずに置き換える - -既定ブランチ宛の Pull Request の本文を NDF の手順(`pr-steps.py create` / `update` とプランの pr のステップ)で書くとき、closing keywords を閉じる予定の参照へ置き換えてから送る(要求の未決 3 の前半)。指し先の字面は変えないため、何を閉じる予定だったかは本文に残る。置き換えたことは `metrics.deferred_closing` と `items` に載る。 - -止める案は採らない。プランの pr のステップは本文を機械で組み、`## 閉じる課題` に `Closes #N` を並べる。止めると、既定ブランチを起点にするリポジトリではスプリントのたびに無人の実行が止まる。 - -根拠: Value 2 / Value 5(MVV 版 3) - -### 決定 6: 閉じる課題を本文から集め続けるため、閉じる予定の参照は専用の形にし、読み手の共通の部品で読む - -閉じる予定の参照の形は `最終工程の後に閉じる: <指し先>` にする(要求の未決 3 の後半)。GitHub の closing keywords を含まないため GitHub は閉じず、`lib/closing-issues.sh` と `lib/closing.py` が closing keywords と同じ指し先の規則で読む。`sprint-close.py`・`merged`・工程の飛ばしの検知の hook・リリースの材料は今の部品を通して読むため、読み手ごとの直しは要らない。 - -`Refs #N` は採らない。「参照」はすでに参照だけの課題(閉じる対象にしない課題)の意味で使っており、同じ形に 2 つの意味が付く。`NDF-Closes #N` のような英語の造語も採らない。語の境界の後に `Closes` が来るため、NDF の読み手(`lib/closing.py` の `CLOSING`)が closing keywords として一致させ、GitHub が閉じるかを読み手ごとに確かめ直すことになる。`--issues` だけで集める案も採らない。受け入れ条件 8 は `--prs` だけで課題が集まることを求め、手で打つ経路で `--issues` を付け忘れると閉じる課題が 0 件になる。 - -最終工程の判定(`final_stage_gap`)は `sprint-close.py` に置き、`lib` に置かない。読み手が 1 つで、`lib/README.md` の「2 つ以上の読み手が使う部品だけを置く」に当たらない。 - -根拠: Value 6 / Value 8(MVV 版 3) - -### 決定 7: 判定の費用を増やさないため、振り返りの行は形だけを見て、指すコメントは読まない - -条件 3 は課題の本文にある行の形(`振り返り: https://github.com/…#issuecomment-<識別子>`)だけで判定する。本文は条件 2 と同じ 1 回の読みで取る。行の URL のコメントを `gh api` で読めば実在を確かめられるが、課題ごとに `gh` の呼び出しが 1 回増える。行は `retrospective` が投稿の後にだけ書く。 - -根拠: Value 10(MVV 版 3) - -### 決定 8: まとめのプランで閉じる時点を 1 つにするため、閉じるのは close のステップだけにし、Skill からの呼び出しは残す - -まとめのプランは `merge →(release-verify)→ retro → close → refine` の順にし、`retro` の指示に `release-verify` と同じく「課題を閉じない(次の close が閉じる)」を足す。プランの外(conductor が Skill を直接通す経路)では、今と同じく最終工程を担う Skill が「スプリントを閉じる」を行う(要求の未決 4)。 - -Skill から呼び出しを外す案は採らない。プランを通らない実行で、閉じる担い手がいなくなる。`sprint-close.py` は判定を自分で行うため、Skill とプランの両方が打っても、早すぎる時点では閉じず、2 度目は `already_closed` になる。プランの中で `retro` に閉じさせない理由は、担当が `--with-verification` を省いて打つと条件 2 を見ずに閉じるためである。 - -モードで並びを分ける案も採らない。今のまとめのプランはどのモードでも `retro` を持ち、`close` を `retro` の後に置けば、受け入れ条件 6 の「最終工程の後、棚卸しの前」をどのモードでも満たす。 - -根拠: Value 4 / Value 6(MVV 版 3) - -### 決定 9: 書き換えの要否を確実に決めるため、宛先が既定ブランチかで決め、既定ブランチを決められないときは置き換える - -置き換えるかは Pull Request の宛先(新しく作るなら `--base` か起点、既存なら `baseRefName`)が既定ブランチ(`lib/repo.py` の `default_branch`)と一致するかで決める。既定ブランチを決められないときは置き換える。置き換えても閉じる予定の参照として NDF の手順で閉じられ、失うものが無い。置き換えずに既定ブランチ宛だったときは、マージで閉じる。 - -`.ndf/worktree.json` の `base_branch` と既定ブランチを比べる案は採らない。GitHub が閉じるかを決めるのは各 Pull Request の宛先であり、`sprint/<名前>` 宛の課題の Pull Request は起点の設定に関わらずマージで閉じない。 - -根拠: Value 5(MVV 版 3) - -### 決定 10: 前のスプリントから持ち越した課題が今回の振り返りの前に閉じないよう、振り返りの行は記録の PR の配布の記録より後のものだけを数える - -振り返りの行は課題の本文に残り続けるため、形だけを見ると、前のスプリントで振り返りを通って開いたまま持ち越した課題が、今回の配布とリリース後テストの後、今回の振り返りの前に条件 3 を満たす。そこで、行が指すコメントの識別子が、記録の PR の最後の配布の記録(閉じる条件 1 が判定する `段階:`)のコメントの識別子以上の行だけを、その実行の振り返りとして数える。配布の記録が本文にあるときは本文に識別子が無いため、記録の PR の最初のコメントの識別子を基準にする。比べ方を「より大きい」でなく「以上」にするのは、今回の振り返りを記録の PR の最初のコメントとして投稿したとき、その識別子が基準と等しくなり、振り返りを終えても閉じられなくなるためである(コメントにある配布の記録と振り返りは別のコメントなので、等しくなるのはこの場合だけ)。記録の PR は条件 1 がすでに 1 回読んでおり、コメントの URL も同じ読みで取れるため、`gh` の呼び出しは増えない(決定 7 と両立する)。#2086 の行(`6392995482`)は記録の PR 2109 の配布の記録(`6391552027`)より大きいことを確かめた。 - -行の指すコメントを読んで投稿時刻を比べる案は採らない。課題ごとに `gh` の呼び出しが 1 回増える(決定 7)。記録の PR の番号を行に書き足して照合する案も採らない。#2086 の行は記録の PR と違う PR を指しており(決定 1)、今ある行と照合できない。 - -根拠: Value 6 / Value 10(MVV 版 3) diff --git a/issues/issue-2228-design.md b/issues/issue-2228-design.md deleted file mode 100644 index b5a9a4d75..000000000 --- a/issues/issue-2228-design.md +++ /dev/null @@ -1,333 +0,0 @@ -# sprint-close: 課題を最終工程の記録を確かめてから閉じ、既定ブランチ宛の PR のマージでは閉じない(#2228) - -## 目的 - -- **何が壊れているか**: 課題が工程の途中で閉じる。`sprint-close.py` は工程の通過を見ず、まとめのプランは振り返りの前に閉じる(#2119)。既定ブランチ宛の Pull Request は本文の closing keywords で、マージの時点に GitHub が閉じる(#2082) -- **誰が困るか**: 棚卸しと振り返りで課題の一覧を読む人と AI。閉じた課題は棚卸しの対象から外れ、不合格の条件や通っていない工程が見えなくなる(s2086 の #2086) -- **直すと何が成り立つか**: NDF のどの経路で閉じても、閉じた課題はその実行の最終工程の記録を持つ。閉じる時点の決まりは `progress-tracking` の 1 か所、判定は `sprint-close.py` の 1 か所にそろう - -## 適用範囲 - -- **働く範囲**: 配布先のリポジトリでも働く。`sprint-close.py`・まとめのプラン・`pr-steps.py`・プランの pr のステップはプラグインの配布物である -- **プロジェクトごとに違うもの**: 既定ブランチと開発の起点(`.ndf/worktree.json` の `base_branch`)は git と設定から読む。最終工程は呼ぶ側が引数 `--final-stage` で渡す -- **当たるモード**: 5 つのモードすべて。最終工程はモードと経路で変わる(`light` は配布、振り返りを通る経路は振り返り、振り返りを通らない `operation` はリリース後テストか配布) - -## あるべき姿の根拠 - -| 根拠 | 種類 | 何を示すか | -| --- | --- | --- | -| s2086 で `sprint-close.py --record-pr 2109 --prs 2092,2088,2090` が #2086 をリリース後テストの前に閉じ、その後のリリース後テストで受け入れ条件 10 が不合格になったが閉じたまま残った(#2119) | 実測 | 呼ぶ側の手順の並びに頼ると、並びを 1 つ書き違えただけで閉じる | -| volareinc/carmo-screening の PR 344 の本文の `Closes #342` で、マージの時刻(2026-10-19T10:07:23Z)に #342 が閉じ、受け入れ条件 11 件が未チェックのまま残った(#2082) | 実測 | 既定ブランチ宛の本文に closing keywords が残ると、NDF の判定より先に GitHub が閉じる | -| #2086・#2216・#2227・#2229 の本文に `振り返り: https://github.com/devbasex/ai-plugins/pull/<番号>#issuecomment-<識別子>` の行があり、#2086 の行は記録の PR(2109)と違う PR(2110)を指す(2026-10-31 に `gh issue view` で確かめた) | 実測 | 振り返りの記録の有無は、記録の PR ではなく課題の本文から課題ごとに読める | -| #2086 の振り返りの行のコメントの識別子(`6392995482`)は、記録の PR 2109 の配布の記録(`段階: 本番`)のコメントの識別子(`6391552027`)より大きい(2026-10-31 に `gh issue view` と `gh pr view --json comments` で確かめた) | 実測 | 振り返りの行がその実行のものかは、記録の PR の最後の配布の記録のコメントより後に投稿されたかで、課題の本文と記録の PR から読める | -| 同じ 4 件と #2172 の本文の `## 進行` の `モード:` は `—` である(同上) | 実測 | 課題の本文のモードからは最終工程を決められない | -| GitHub は既定ブランチへのマージのときだけ本文の closing keywords で課題を閉じる(`lib/closing-issues.sh` の冒頭の説明と、`develop` 宛のこのリポジトリで課題がマージで閉じない今の運用) | 実測 | 書き換えるのは宛先が既定ブランチの Pull Request だけでよい | - -要求と受け入れ条件は #2228 の本文にある(コピーは [issue-2228-requirements.md](issue-2228-requirements.md))。この文書は「どう作るか」だけを扱う。 -決定の記録は [issue-2228-design-decisions.md](issue-2228-design-decisions.md) に分けた。子の #2082・#2119 の設計もこの文書が持つ。 - -## ドメインモデル - -### コンテキスト - -| コンテキスト | 何の語が 1 つの意味に決まるか | -| --- | --- | -| 工程(`ndf-workflow`) | 最終工程・最終工程の記録・スプリント課題・閉じる予定の参照・閉じる条件 | -| GitHub(外部の系) | closing keywords・既定ブランチ・課題の状態(OPEN / CLOSED) | - -工程が下流、GitHub が上流の関係で、工程の側が**腐敗防止層**を置く。GitHub の closing keywords は「既定ブランチへマージしたら閉じる」という上流の規則で、工程の「最終工程の後に閉じる」を壊す。PR の本文を書く手順は `lib/closing.py` の `defer_closing` を通し、既定ブランチ宛の本文では closing keywords を工程の語(閉じる予定の参照)へ翻訳する。読む側は 2 つの形を同じスプリント課題として読む。 - -### 集約 - -| 集約 | 持ち主(書き換えてよいもの) | 根 | エンティティ | 値オブジェクト | -| --- | --- | --- | --- | --- | -| 課題の閉じ方 | `sprint-close.py`(課題の状態・ボードの `Done`・受け入れ条件の印) | スプリント課題(`(リポジトリ, 番号)`) | — | 最終工程・最終工程の記録・判定の結果(`result` / `reason`) | -| 閉じる指定 | `lib/closing.py` の `defer_closing`(本文の閉じる指定の形を決める唯一の関数。`pr-steps.py` と `supervise_lib/pr.py` は通して書くだけ) | Pull Request の本文 | — | closing keywords・閉じる予定の参照 | -| まとめのプラン | `supervise_lib/sprint_close_steps.py` と `sprint.py` の `close_plan` | プラン | ステップ | ステップの並び(`next`) | - -課題の閉じ方は閉じる指定を ID(課題の参照)でだけ読む。まとめのプランは課題の閉じ方を `sprint-close.py` の起動でだけ使い、閉じてよいかを自分で判定しない。 - -### 不変条件 - -| # | 集約 | 条件 | 破れたときの扱い | -| --- | --- | --- | --- | -| I1 | 課題の閉じ方 | 課題を閉じ、ボードを `Done` にするのは、その課題のその実行の最終工程の記録があるときだけである。振り返りの行は、指すコメントの識別子が記録の PR の最後の配布の記録のコメントの識別子(記録が本文にあるときは「記録の PR の読み」の基準)以上のものだけを数え、前の実行(前のスプリント)の行は数えない | 閉じない。`kept_open` と、通っていない工程の名前を含む `reason` で返す | -| I2 | 課題の閉じ方 | 最終工程の記録を読む置き場(課題の本文)を読めないとき、記録があるとは読まない | 閉じない。`failed` と打ち直しの `cmd` で返し、`status` は `stopped`(終了コード 1) | -| I3 | 課題の閉じ方 | `--final-stage` を省いたときの最終工程は `振り返り`(最も後ろ)である。省いても閉じる条件は緩まない | — (既定値で守る) | -| I4 | 課題の閉じ方 | 最終工程が `リリース後テスト` のとき、閉じる条件 2(リリース後テストの行がすべて合格)を `--with-verification` の有無にかかわらず見る | 閉じない(今の条件 2 の扱い) | -| I5 | 課題の閉じ方 | `--record-pr 0` と `--record-pr unknown` の今の扱いは変わらない。`unknown` は最終工程の記録を読まずにすべて `kept_open` で返す | — | -| I6 | まとめのプラン | `next` のつながりで、`close` は `retro` の後、`refine` の前にある。`retro` と `release-verify` の指示は課題を閉じない。まとめのプランはどのモードでも `retro` を持つため、プランの中の最終工程はどのモードでも振り返りで、`close` は `--final-stage 振り返り` を明示して渡す(I3 の既定に頼らない)。`配布` と `リリース後テスト` は、プランの外で最終工程を担う Skill(`light` の `release`、振り返りを通らない `operation` の `release-verification` か `release`)だけが渡す | プランを組む関数のテストで落ちる | -| I7 | 閉じる指定 | 宛先が既定ブランチ(既定ブランチを決められないときを含む)の Pull Request を NDF の手順で書くと、本文に closing keywords が残らず、置き換えた指し先は同じ課題を指す閉じる予定の参照になる | — (書く前に `defer_closing` を通す) | -| I8 | 閉じる指定 | 宛先が既定ブランチでない Pull Request の本文は書き換えない | — | -| I9 | 閉じる指定 | 閉じる予定の参照は GitHub の closing keywords を含まない | `closing_words` が一致を返したらテストで落ちる | -| I10 | 課題の閉じ方 | スプリント課題は closing keywords・閉じる予定の参照・`--issues` の和であり、閉じる予定の参照が指す課題を参照だけの課題にしない | — | - -### ドメインイベント - -| # | イベント | 発生元 | 受け手 | -| --- | --- | --- | --- | -| E1 | 課題の Pull Request・スプリントの Pull Request がマージされた | 承認ゲート 2 の後のマージ(`merge-when-green`) | GitHub(既定ブランチ宛でも閉じる予定の参照では閉じない。I7) | -| E2 | 配布を終え、配布の記録を記録の PR に置いた | `release`・`release-steps.py record` | `sprint-close.py`(閉じる条件 1) | -| E3 | リリース後テストの結果を記録した | `release-verification` | `sprint-close.py`(閉じる条件 2) | -| E4 | 振り返りの記録を投稿し、課題の本文に辿る経路の行を足した | `retrospective` | `sprint-close.py`(閉じる条件 3) | -| E5 | 課題ごとに最終工程の記録を判定した | `sprint-close.py` | 結果 JSON の読み手(プランの `close` のステップ・conductor・Skill の担当) | -| E6 | 判定を通った課題のボードを `Done` にし、閉じた | `sprint-close.py` | ボードの自動化・`backlog-refinement` | -| E7 | 棚卸しを始めた | プランの `refine`・工程表の次の工程 | `backlog-refinement` | - -### 用語 - -| 用語 | 意味 | 用語集への反映 | -| --- | --- | --- | -| 最終工程 | 棚卸しの前にその実行で最後に通る工程。振り返りを通るなら振り返り、通らずリリース後テストを通るならリリース後テスト、どちらも通らなければ配布。まとめのプランは `retro` を必ず通すため、プランの中ではどのモードでも振り返りになる(I6) | 意味の変更(`ndf-workflow`。配布の場合を足す) | -| 最終工程の記録 | 最終工程を終えたことを示す、GitHub に残った記録。配布は配布の記録の `段階:`、リリース後テストはその課題の行、振り返りは課題の本文の `振り返り: <コメントの URL>` の行のうち、指すコメントの識別子が記録の PR の最後の配布の記録のコメントの識別子(記録が本文にあるときは「記録の PR の読み」の基準)以上のもの(その実行の振り返り) | 追加(`ndf-workflow`) | -| 閉じる予定の参照 | Pull Request の本文に `最終工程の後に閉じる: #<番号>` と書く形。GitHub は閉じず、`sprint-close.py` がスプリント課題として集める | 追加(`ndf-workflow`) | -| スプリント課題 | 「スプリントを閉じる」が閉じる対象にする課題。スプリントの Pull Request の本文の closing keywords と閉じる予定の参照が指す課題と、`--issues` で渡した課題の和 | 意味の変更(`ndf-workflow`。閉じる予定の参照を足す) | - -## 機能一覧 - -| # | 機能 | 誰が使うか | -| --- | --- | --- | -| F1 | 課題ごとに最終工程の記録を確かめ、無ければ閉じずに理由を返す | まとめのプランの `close`・最終工程を担う Skill の担当・conductor | -| F2 | 呼ぶ側が最終工程を引数で渡す(省けば振り返り) | 同上 | -| F3 | まとめのプランを「リリース後テスト → 振り返り → 課題を閉じる → 棚卸し」の順に組む | `supervise.py new close` を打つ conductor | -| F4 | 既定ブランチ宛の Pull Request の本文の closing keywords を閉じる予定の参照へ置き換える | `/ndf:pr`(`pr-steps.py`)とプランの pr のステップ | -| F5 | 閉じる予定の参照をスプリント課題として集める | `sprint-close.py`・`merged`・工程の飛ばしの検知の hook・リリースの材料 | - -## 構成要素 - -| 要素 | 責務 | -| --- | --- | -| `scripts/sprint-close.py` | 引数 `--final-stage` を受け、課題ごとに閉じる条件 3(最終工程の記録)を判定する。判定の関数 `final_stage_gap(stage, body)` はこのファイルに置く(読み手が 1 つのため `lib` に置かない。決定 6) | -| `scripts/lib/closing.py` | 閉じる予定の参照の形(`DEFERRED`)を持つ。`defer_closing(text)` が closing keywords を置き換え、`closing_issues` / `closing_refs` / `closing_numbers` が 2 つの形をどちらも読む。`closing_words` は closing keywords だけを読む(コミットの検査のため) | -| `scripts/lib/closing-issues.sh` | 閉じる予定の参照も取り出す。出力の形(`<リポジトリ>\t<番号>`)は変えない | -| `scripts/lib/repo.py` | `merge_closes_issues(root, base)`: 宛先が既定ブランチか、既定ブランチを決められないときに真 | -| `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 が閉じる)」を足す | -| `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`) | 閉じる時点・順序・閉じる条件の写しを外し、正本を指す。順序の説明の文を新しい並びに直す | -| `docs/glossary/glossary.json`・`docs/glossary.md` | 用語の表の 4 語を反映し、`glossary.py render` で作り直す | - -```mermaid -graph LR - subgraph 書く側 - PRS[pr-steps.py] --> DEF[lib/closing.py defer_closing] - PLPR[supervise_lib/pr.py] --> DEF - PRS --> MCI[lib/repo.py merge_closes_issues] - PLPR --> MCI - end - subgraph 読む側 - SC[sprint-close.py] --> CIS[lib/closing-issues.sh] - MRG[merged・hook] --> CIS - REL[release_lib] --> CPY[lib/closing.py closing_refs] - end - subgraph まとめのプラン - RV[release-verify] --> RT[retro] --> CL[close] --> RF[refine] - end - CL --> SC - DOC[progress-tracking の正本] -.決まり.-> SC - DOC -.決まり.-> CL -``` - -図に含めない要素: 契約の写し(`4-close.json`)・正本を指すように付け替える Skill と references・用語集。どれも呼び出しの関係を持たない。 - -### システムの文脈 - -```mermaid -graph LR - NDF[NDF の手順] -->|本文を書く・課題を閉じる| GH[(GitHub: PR・課題・ボード)] - GH -->|本文・コメント・課題の本文を読む| NDF - GH -->|既定ブランチへのマージで closing keywords の課題を閉じる| GH -``` - -配置は変わらない。どの要素も conductor・supervisor・worker が動く機械の上で起動され、状態は GitHub に置く(手元の通過記録・プランの状態ディレクトリを判定に使わない。決定 1)。 - -## 構造 - -触る関数とその関係(Python のモジュールを型として描く)。 - -```mermaid -classDiagram - class sprint_close { - +cmd_close(a) - +final_stage_gap(stage, body) str|None - -_close_item(a, ctx, repo, n, kept_all, verdicts) - -_judge_and_mark(a, ctx, repo, n, rows) - } - class closing { - +DEFERRED - +defer_closing(text) (str, list) - +closing_words(text) list - +closing_issues(text) list - +closing_refs(text, repo) list - } - class repo { - +default_branch(root) - +merge_closes_issues(root, base) bool - } - class pr_steps { - +upsert(a, must_exist) - } - class supervise_pr { - -_publish(ctx, base, branch, title, body) - } - pr_steps --> closing - pr_steps --> repo - supervise_pr --> closing - supervise_pr --> repo - sprint_close --> closing : closing-issues.sh 経由 -``` - -## 入出力の契約 - -### `sprint-close.py` - -```text -sprint-close.py --record-pr [--final-stage 配布|リリース後テスト|振り返り] - [--prs 1,2] [--issues 3,4] [--with-verification] [--label …] [--dry-run] [--root ] [--repo ] -``` - -| 項目 | 変更後 | -| --- | --- | -| `--final-stage` | 新しい引数。値は 3 つ。省けば `振り返り`。それ以外の値は呼び出しの誤り(終了コード 3) | -| 閉じる条件 3 | 最終工程ごとに、その課題の最終工程の記録を見る(下の表)。条件 1・2 の後に判定する | -| `items[].reason`(条件 3 を満たさない) | `最終工程(<工程>)の記録が無い: <何が無いか>`。`result` は `kept_open`。既に閉じていれば `closed_unverified`(開き直さない。今の条件 2 と同じ扱い) | -| 課題の本文を読めない | `result: failed`・`reason: 本文を読めない(最終工程の記録を確かめられない)`・`cmd` は同じ呼び出し。`status: stopped`・終了コード 1(今の `failed` の扱い) | -| `metrics.final_stage` | 新しい値。判定に使った最終工程 | -| `decisions` | 1 件足す。`{"decision": "最終工程を <工程> として判定した", "basis": "--final-stage <値>(省略時は振り返り)"}` | -| 終了コード | 0 / 1 / 2 / 3 の意味は変えない | - -| 最終工程 | 最終工程の記録 | 読む置き場 | -| --- | --- | --- | -| `配布` | 閉じる条件 1(最後の配布の記録の `段階:` が `本番` か `配布なし`。`--record-pr 0` は満たす) | 記録の PR(今と同じ) | -| `リリース後テスト` | 閉じる条件 2(`--with-verification` を付けたのと同じ判定) | 記録の PR(今と同じ) | -| `振り返り` | 課題の本文に、行頭から `振り返り: https://github.com/<所有者>/<リポジトリ>/(issues|pull)/<番号>#issuecomment-<識別子>` の行があり、そのうち 1 つ以上の `<識別子>` が、比べる基準の識別子(下の「記録の PR の読み」の `dist_comment_id`)以上(等しいのは、本文にある記録で、振り返りを記録の PR の最初のコメントとして投稿したとき。`--record-pr 0` は配布の記録が無いため、行があれば満たす) | 課題の本文(`gh issue view --json state,body`)と記録の PR(閉じる条件 1 の 1 回の読み。`gh` の呼び出しを増やさない) | - -記録の PR の読み(`read_record` と `lib/dist_record.py` の `parse_record`)は、比べる基準の識別子を閉じる条件 1 と同じ 1 回の `gh pr view --json body,comments` から返すように変える。 - -| 関数 | 変更後 | -| --- | --- | -| `read_record` | 連結した文字列に加えて、部分ごとの「先頭の行の番号と、コメントの識別子」の並びを返す。コメントの識別子は `comments[].url` の `#issuecomment-<識別子>` の数字。本文(先頭の部分)の識別子は `None` | -| `parse_record` | 引数に部分の並びを足し、戻り値に `dist_comment_id` を足す。最後の配布の記録の見出しの行を含む部分の識別子である。その部分が本文なら、記録の PR の最初のコメントの識別子を使い、コメントが 1 件も無ければ `None`。記録の PR はその実行で作るため、最初のコメントは前の実行の振り返りより後にあり、比べ方が「以上」なので、今回の振り返りがその最初のコメントでも数える | -| 条件 3(振り返り)で `dist_comment_id` が `None` | 比べる基準が無いため満たさない。`kept_open`(既に閉じていれば `closed_unverified`)と `最終工程(振り返り)の記録が無い: 比べる配布の記録のコメントが無い` を返す | - -### `pr-steps.py create` / `update` - -| 項目 | 変更後 | -| --- | --- | -| 本文 | 宛先が `merge_closes_issues` に当たれば、`Closes #12` などを `最終工程の後に閉じる: #12` へ置き換えてから送る。指し先の字面(`#12`・`owner/repo#12`・課題の URL)は変えない | -| `metrics.deferred_closing` | 新しい値。置き換えた指し先の字面の配列(置き換えなければ空) | -| `items` | 置き換えたら `{"kind": "closing", "name": "<指し先>", "result": "deferred"}` を指し先ごとに足す | -| `metrics.closing_issues_in_body` | 2 つの形の指し先をどちらも載せる | -| `status` | 置き換えは `ok` のまま(欠けではない) | - -### 閉じる予定の参照の形 - -```text -最終工程の後に閉じる: <指し先> -``` - -`<指し先>` は closing keywords と同じ 3 つ(`#<番号>`・`<所有者>/<リポジトリ>#<番号>`・課題の URL)。`:` の前後の空白は 0 個以上を許す。1 つの指し先に 1 つ書く(closing keywords と同じ規則)。 - -## 処理の流れ - -### `sprint-close.py` の課題 1 件の判定 - -```mermaid -flowchart TD - A[課題 1 件] --> B{record-pr が unknown か
条件 1 を満たさない} - B -->|当たる| K1[kept_open
今の理由] - B -->|当たらない| C{条件 2 を見るか
with-verification
または最終工程がリリース後テスト} - C -->|見る| D[錠の中で状態と本文を 1 回読む] - C -->|見ない| E[最終工程が振り返りなら
状態と本文を 1 回読む] - D -->|読めない| F[failed] - E -->|読めない| F - D --> G{条件 2} - G -->|満たさない| K2[kept_open / closed_unverified] - G -->|満たす| H - E --> H{条件 3
final_stage_gap} - H -->|記録が無い| K3[kept_open / closed_unverified
最終工程の記録が無い] - H -->|記録がある| I[受け入れ条件の印 → ボード Done → 閉じる → 読み直す] -``` - -条件 3 は条件 2 と同じ 1 回の本文の読みを使う(`gh` の呼び出しを増やさない)。比べる基準の識別子は、条件 1 で記録の PR を読んだ 1 回の結果から `parse_record` が返す `dist_comment_id` を使う(「記録の PR の読み」)。印を書くのは条件 3 も満たしたときだけで、条件 3 を満たさない課題の本文は書かない。`--dry-run` は判定まで行い、書かない。 - -### まとめのプランの並び - -```mermaid -flowchart LR - M[merge] -->|配布の記録あり| RV[release-verify
課題を閉じない] - M -->|配布の記録なし| RT - RV --> RT[retro
課題を閉じない] - RT --> CL[close
sprint-close.py --final-stage 振り返り] - CL -->|0 で終わったときだけ| RF[refine] -``` - -### Pull Request の本文を送る - -```mermaid -sequenceDiagram - participant W as pr-steps.py / supervise_lib/pr.py - participant R as lib/repo.py - participant C as lib/closing.py - participant G as gh - W->>R: merge_closes_issues(root, base) - alt 宛先が既定ブランチ(決められないときを含む) - W->>C: defer_closing(body) - C-->>W: 置き換えた本文と指し先 - end - W->>G: gh pr create / gh pr edit(本文) -``` - -## 非機能の実現方式 - -| 大項目 | 実現方式 | -| --- | --- | -| 運用・保守性 | 閉じる時点の決まりは `progress-tracking` の「スプリントを閉じる」だけが持つ。判定は `sprint-close.py` の `final_stage_gap` と既存の条件 1・2 だけに置き、まとめのプランと Skill の本文は `--final-stage` の値を渡すだけにする。閉じる指定の形は `lib/closing.py` だけが持ち、`closing-issues.sh` は同じ形を読む(2 つの読み手が同じ結果を返すことをテストで縛る) | -| 移行性 | 同じ版で呼ぶ側(まとめのプラン・Skill の本文)も直す。利用者の手での移行は要らない。この版より前に振り返りを通った課題は既に本文に辿る経路の行を持つ(#2216・#2227・#2229 で確かめた)ため、そのまま閉じられる。行を持たずに開いている課題は `kept_open` で残り、`next` が「振り返りを通すか、確かめて手で閉じる」を示す(決定 4) | - -## 決定の記録 - -[issue-2228-design-decisions.md](issue-2228-design-decisions.md) に分けた。 - -## テスト設計 - -| 受け入れ条件・不変条件 | どの振る舞いで縛るか | どう壊したら落ちるべきか | -| --- | --- | --- | -| 受け入れ条件 1 | 文書の参照はチェックスクリプトと `grep` で見る(文言を照合するテストは書かない) | — (マージ前に `grep` で、閉じる条件と順序を持つ文書が正本の 1 か所であることを見る) | -| 受け入れ条件 2・I1・I3 | 本文に辿る経路の行が無い課題で、`--final-stage` を省いて打つと、`--with-verification` の有無の両方で `kept_open` と「振り返り」を含む `reason` が返り、閉じる・ボードを書く `gh` の呼び出しが無い | 既定値を `配布` にする・条件 3 を `--with-verification` の経路だけで見る・ボードを判定の前に書く | -| 受け入れ条件 2・I1(前の実行の行) | 本文に振り返りの行があるが、その識別子が記録の PR の最後の配布の記録のコメントの識別子より小さい課題(前のスプリントから持ち越した課題)で、`--final-stage` を省いて打つと `kept_open` と「振り返り」を含む `reason` が返る。識別子が大きい行を足すと閉じる | 行の形だけを見る・配布の記録の識別子と比べない・最初の配布の記録と比べる | -| 受け入れ条件 3・I2 | 課題の本文の読みが失敗すると `failed`・`status: stopped`・終了コード 1 になる | 読めないときに記録ありと読む・`kept_open` で `ok` を返す | -| 受け入れ条件 2・I1(比べる基準の取り方) | 記録の PR の最後の配布の記録がコメントにあれば、`parse_record` の `dist_comment_id` がそのコメントの識別子になる。本文にあれば最初のコメントの識別子、コメントが無ければ `None` で、`None` のときは振り返りの行があっても `kept_open` と「比べる配布の記録のコメントが無い」を含む `reason` が返る。本文にある記録で、振り返りの行が記録の PR の最初のコメントを指す課題は閉じる(識別子が基準と等しい)。どの場合も記録の PR を読む `gh` の呼び出しは 1 回 | 識別子を取るために `gh` をもう 1 回呼ぶ・本文の記録で行の有無だけを見る・最初の配布の記録のコメントを使う・基準と等しい識別子を数えない | -| 受け入れ条件 4・I4・I5 | 辿る経路の行があり、行がすべて合格の課題で印・`Done`・閉じるが今と同じ順で起きる。`--record-pr 0` で辿る経路の行があれば閉じる。`unknown` では本文を読まずにすべて `kept_open` | 条件 3 を条件 2 より前に置いて印を書かない・`unknown` で本文を読む | -| I4 | `--final-stage リリース後テスト` で `--with-verification` を付けずに打つと、不合格の行を持つ課題が閉じない | 最終工程の値を条件 2 に結び付けない | -| 受け入れ条件 5・I6 | 振り返りを通るまとめのプランの `next` をたどった `id` の並びが `release-verify → retro → close → refine`(記録なしでは `retro → close → refine`)。`retro` と `release-verify` の指示に閉じない旨がある | `close` の `next` を `retro` に戻す・`merge` の `next` を `close` にする | -| 受け入れ条件 6 | `light` を含むどのモードで組んでも、`close` は最後の工程のステップ(`retro`)の後、`refine` の前にある | モードで並びを分けて `close` を `retro` の前に置く | -| 受け入れ条件 7・I7・I9 | 既定ブランチと起点が同じ一時のリポジトリで `pr-steps.py create` / `update` を流すと、`gh` に渡る本文に closing keywords が無く、閉じる予定の参照が同じ指し先で残る。既定ブランチを決められない構成でも同じ。置き換えた本文に `closing_words` が何も返さない | 置き換えを `create` だけにする・既存の PR の宛先を見ない・印の語に `close` を含める | -| 受け入れ条件 7(プランの経路) | `supervise_lib/pr.py` の `_publish` が既定ブランチ宛で `gh` に渡す本文に closing keywords が無い | `_publish` で置き換えを通さない | -| 受け入れ条件 8・I10 | 閉じる予定の参照だけを持つ PR で `sprint-close.py --prs <番号> --dry-run` を打つと、その課題が `would_close`(辿る経路の行があるとき)で、参照だけの課題にも終了コード 2 にもならない。`closing-issues.sh` と `closing.closing_refs` が同じ本文から同じ指し先を返す | `closing-issues.sh` だけに形を足す・参照だけの課題の除外に新しい形を入れない | -| 受け入れ条件 9・I8 | 起点が既定ブランチと違う構成(宛先 `develop`)では、本文が書き換わらず、`sprint-close.py` が closing keywords から課題を集める(既存のテストが通る) | 宛先を見ずに常に置き換える | -| 受け入れ条件 10 | 子の課題で確かめる | — | -| 受け入れ条件 11 | リリース後テストで、最初のスプリントの課題の `closedAt` が本文の辿る経路の行が指すコメントの投稿時刻より後であることを見る | — | - -## 設計の結果 - -| 課題 | 扱い | 取り込み先 | 触るファイル | -| --- | --- | --- | --- | -| #2228 | 実装する | — | `plugins/ndf/scripts/sprint-close.py`、`plugins/ndf/scripts/lib/closing.py`、`plugins/ndf/scripts/lib/dist_record.py`、`plugins/ndf/scripts/lib/closing-issues.sh`、`plugins/ndf/scripts/lib/repo.py`、`plugins/ndf/scripts/pr-steps.py`、`plugins/ndf/scripts/supervise_lib/`、`plugins/ndf/scripts/supervise.py`、`plugins/ndf/scripts/tests/`、`plugins/ndf/skills/progress-tracking/SKILL.md`、`plugins/ndf/skills/pr/SKILL.md`、`plugins/ndf/skills/release-verification/SKILL.md`、`plugins/ndf/skills/retrospective/SKILL.md`、`plugins/ndf/skills/release/SKILL.md`、`plugins/ndf/skills/merged/SKILL.md`、`plugins/ndf/skills/development-workflow/references/`、`docs/glossary/glossary.json`、`docs/glossary.md` | -| #2082 | 取り込む | #2228 | — | -| #2119 | 取り込む | #2228 | — | - -## 未確認のまま残ること - -| 項目 | 内容 | -| --- | --- | -| コメントの識別子の大小と投稿の順 | GitHub のコメントの識別子が投稿の順に大きくなることに頼る(#2086 と記録の PR 2109 の 1 組で確かめた)。順に並ばない例が出たら、投稿時刻の比較へ替える | -| 配布の記録が本文だけにある記録の PR | 本文には識別子が無いため、最初のコメントの識別子を基準に使い、等しいものも数える。記録の PR がその実行で作られ、最初のコメントが前の実行の振り返りより後にあることに頼る。コメントの無い記録の PR では振り返りを最終工程とする課題が閉じない(安全側に倒す)。記録の PR が本文の配布の記録だけで終わる実例は確かめていない | -| `--record-pr 0` の前の実行の行 | 配布の記録が無いため比べる基準が無く、前のスプリントの行を持つ持ち越しの課題は、その実行の振り返りの前に条件 3 を満たしうる。本番の記録が無い経路に限る | -| 辿る経路の行の中身 | 行の URL のコメントが実在するか・振り返りの記録の形かは読まない(課題ごとに `gh` を 1 回増やすため。決定 7) | -| `--with-verification` を付け忘れた振り返りの経路 | 振り返りの経路で `--with-verification` を省くと、条件 2 を見ずに閉じる(今と同じ)。順序はプランが守るが、不合格の行を持つ課題が閉じうる。範囲外の課題 #2293 として起票した | -| `closing-issues.sh` の日本語の一致 | `grep -E` が利用者の locale(`C` を含む)で `最終工程の後に閉じる` をバイト列として一致させるかを、実装で走らせて確かめる | -| 利用者が GitHub の画面で本文を書き直したとき | NDF の手順を通らない書き込みは置き換えない(要求の対象範囲の外) | diff --git a/issues/issue-2228-requirements.md b/issues/issue-2228-requirements.md deleted file mode 100644 index 384999e3f..000000000 --- a/issues/issue-2228-requirements.md +++ /dev/null @@ -1,169 +0,0 @@ -# #2228: 課題を閉じる時点を 1 つにし、最終の工程を通ってから閉じる - -正は課題の本文(#2228)で、この文書はその写しである。`spec-copy.py write` で作り直す。手で直さない。 - -## 依頼(原文) - -この課題は、起票者(AI)が子の 2 件(#2082・#2119)をまとめて起こした親の課題である。利用者の指示の原文は課題にも記録にも見当たらない(2026-10-31 の利用者の方針 5 点〔`--loop` を残す・codex / agy / kiro への配布を cross 系に絞る・全工程で統一した JSON レポート・並列に強く・テストを削る〕には、課題を閉じる時点の項目が無い)。マイルストーン「26 自律実行の信頼性」の説明の主題 2 と、起票時の本文を写す。 - -> 課題を閉じる時点を 1 つにし、工程を通ってから閉じる(親 B) - -(書き手: 起票者〔マイルストーンの説明に AI が書いた主題。利用者の発言の原文ではない〕、日付: 2026-10-31) - -起票時の本文(題「課題を閉じる時点を 1 つにし、最終の工程を通ってから閉じる」): - -> ## 何が困るか -> -> 課題が工程の途中で閉じる。閉じる経路が 3 つあり、どれも工程の通過を見ない。 -> -> | 子 | 閉じる経路 | -> | --- | --- | -> | #2082 | 既定ブランチ宛の実装 PR の本文のclosing keywordsで、GitHub がマージの時点に閉じる | -> | #2119 | `sprint-close.py` が工程の通過を見ない。雛形の `supervise_lib/sprint.close_plan` は release-verify → close → retro の順で、振り返りの前に閉じる(`progress-tracking/SKILL.md` の「振り返りを通る変更では、retrospective が記録を投稿した後に閉じる」と食い違う) | -> -> ## 修正レイヤー -> -> **課題を閉じる時点の正本。** `progress-tracking` の「スプリントを閉じる」を正本とし、`sprint-close.py` の入口で工程の通過を確かめる。`sprint.close_plan` の順序と、`pr` の宛先の表(closing keywordsを使う条件)をそれに従わせる。 -> -> ## 完了条件 -> -> - 最終の工程を通っていない課題は、どの経路でも閉じない -> - 閉じる順序が `progress-tracking` と雛形で一致する -> - 工程の通過は親 A のレポートから判定できる(A に依存) - -(書き手: 起票者、日付: 2026-10-31。利用者の指示の原文として扱わない。引用の中の「closing keywords」は、原文では用語集で廃した語で書かれていたものを用語集の語へ置き換えた) - -子の課題: - -- #2082「既定ブランチ宛の実装 PR の本文のclosing keywordsで、マージの時点に課題が閉じ、仕上げの工程と受け入れ条件のチェックが閉じた課題に残る」(volareinc/carmo-screening#342 の振り返りから起票) -- #2119「`sprint-close.py` が工程の通過を見ず、振り返りの前に課題を閉じる」(#2086 の振り返りから起票。スプリント s2086 で、リリース後テストの前に #2086 が閉じ、その後のリリース後テストで受け入れ条件 10 が不合格になったが閉じたまま残った) -- 親 A は #2227「全工程の結果を統一した JSON レポートにし、失敗・未収束・未記録を ok で返さない」 - -## 起票者の推定 - -利用者の指示の原文が無いため、題・本文の条件はどれも起票者の推定である。そのうち要求の形を決める条件を並べる。承認ゲート 1 で利用者が確かめるまで、利用者の決定として扱わない。 - -| # | 条件 | 推した出所 | この要求での扱い | -| --- | --- | --- | --- | -| S1 | 閉じる時点の正本は `progress-tracking` の「スプリントを閉じる」の 1 か所である | 本文の「修正レイヤー」 | 受け入れ条件 1 | -| S2 | 工程の通過を確かめるのは `sprint-close.py` の入口である(呼ぶ側の手順の並びに頼らない) | 本文の「修正レイヤー」、#2119 の起票者の推定 (a) | 受け入れ条件 2・3 | -| S3 | まとめのプラン(`supervise.py new close`)の並びを、振り返り → 課題を閉じる → 棚卸しにする | 本文の「何が困るか」、#2119 の受け入れ条件 3・4 | 受け入れ条件 5・6 | -| S4 | 既定ブランチ宛の Pull Request の本文には、マージで課題を閉じる closing keywords(PR 本文に `Closes #123` のように書くと、マージ時にその課題を自動で閉じる GitHub の機能)を残さない | 本文の「何が困るか」の #2082 の行、#2082 の起票者の推定の 1 案目。#2082 の 2 案目(自動で閉じるのを前提にし、閉じた後でも受け入れ条件に印を付けられるようにする)は、「最終の工程を通っていない課題は、どの経路でも閉じない」と両立しない | 受け入れ条件 7・8・9。2 案目は採らない | -| S5 | 工程の通過は親 A(#2227)のレポートから判定できる | 本文の「完了条件」3 点目 | 前提 3・未決 1。判定の材料を何にするかは設計で決める | -| S6 | 閉じる経路は 3 つある | 本文の「何が困るか」1 行目。表には 2 行しか無い | 前提 1 で、この要求が扱う経路を 3 つに数え直す | - -## 目的 - -- 課題が閉じた時点で、その実行の最終工程(棚卸しの前に最後に通る工程)が終わっているようにする。閉じた課題は棚卸しの対象から外れ、不合格の条件や未通過の工程が見えなくなるためである(#2119 の s2086 の経緯) -- 閉じる時点の決まりを 1 か所に置き、スクリプト・まとめのプラン・Pull Request の本文の規則がそれに従うようにする。今は文書の決まりと雛形の並びが食い違い、決まりを守るのは呼ぶ側(conductor・引継ぎ文書)の手順の並びに頼っている - -## 前提 - -- 前提 1: この要求が扱う「閉じる経路」は次の 3 つである。(a) GitHub が Pull Request のマージの時点に、本文の closing keywords で課題を閉じる(#2082)、(b) `sprint-close.py` を、まとめのプラン・conductor・Skill の手順のどれかが打つ(#2119)、(c) `sprint-close.py` がボードの `Status` を `Done` にしたことで、ボードの `Auto-close issue` が課題を閉じる((b) の中の 1 手で、(b) の判定を通らないと起きない) -- 前提 2: 「最終工程」は、`progress-tracking` の「スプリントを閉じる」の定義(棚卸しの前にその実行で最後に通る工程)と、`development-workflow` の工程表(`workflow-common.sh` の `WF_STAGE_MATRIX`)のモードごとの必須・条件付きの区分で決まる。`light` は `配布`、`standard` と `legacy-refactor` と `documentation` は `振り返り`、`operation` はその実行で通る条件付きの工程による -- 前提 3: 親 A(#2227)の結果 JSON の共通形式が先に入る。工程の通過を判定する材料は、#2227 の形式の結果(`status` が `ok` のもの)か、それと同じ版に入る記録から取る。今の通過記録(`progress-record.sh` が積むファイル)と本文の `## 進行` は「工程に入った時点」の記録で、工程を終えたことを表さないため、それだけで通過とは読まない -- 前提 4: `--record-pr 0`(本番の記録なし)と `--record-pr unknown`(記録の置き場が分からない)の今の扱いは変えない。工程の通過の判定は、その上に足す閉じる条件である -- 前提 5: 子の 2 件(#2082・#2119)の受け入れ条件は、この課題の受け入れ条件に含める(受け入れ条件 10)。設計はこの課題で 2 件をまとめて行い、実装の Pull Request を子ごとに分けるかは計画で決める -- 前提 6: 振り返りの記録は、記録の Pull Request のコメントとして投稿される(`retrospective` の今の決まり)。この要求はその置き場を変えない - -## 対象範囲 - -含む: -- `progress-tracking` の「スプリントを閉じる」を閉じる時点の正本として、「最終工程を終えてから閉じる」の判定の材料と順序を書く -- `sprint-close.py` の入口で、課題ごとに最終工程を終えたかを判定し、終えていない課題を閉じない -- まとめのプラン(`supervise_lib/sprint.py` の `close_plan` と `sprint_close_steps.py`)の並びを正本に合わせる -- `pr` の宛先の表と「closing keywords は本文だけに書く」を、既定ブランチ宛の Pull Request で closing keywords を残さない形にする。closing keywords を持たない Pull Request から閉じる課題を集める手段(`--issues` か、それに代わるもの)を `sprint-close.py` に持たせる -- 正本を写している文書(`retrospective`・`release-verification`・`release`・`development-workflow` の references)の参照の付け替え - -含まない: -- 利用者が手で `gh issue close` や GitHub の画面で閉じること(NDF の経路ではない) -- 棚卸しが「やらない」と決めた課題を `not planned` で閉じること(`backlog-refinement` の `no-work.md`。工程を通らずに閉じるのが意図の経路で、最終工程の判定の対象にしない) -- `check-trigger.py` が Pull Request を閉じること(課題ではない) -- 親 A(#2227)の結果 JSON の形式そのものの変更 -- 他のリポジトリ(例: volareinc/carmo-screening)の既存の課題・Pull Request の書き直し - -## ドメインイベント - -| # | イベント | 引き金 | 失敗したとき | 順序の前提 | -| --- | --- | --- | --- | --- | -| E1 | 課題の Pull Request・スプリントの Pull Request がマージされた | 承認ゲート 2 の後のマージ | 宛先が既定ブランチで本文に closing keywords が残っていた → GitHub が課題を閉じる(受け入れ条件 7・8 で起きなくする) | — | -| E2 | 配布(開発版・本番)を終え、配布の記録を記録の Pull Request に置いた | `release` | 配布が失敗した → 閉じる条件 1 を満たさず、課題は開いたまま残る(今と同じ) | E1 | -| E3 | リリース後テストの結果を記録した | `release-verification`(リリース後テストを通る経路のとき) | 不合格・保留の行がある → 課題は閉じない(今の閉じる条件 2) | E2 | -| E4 | 振り返りの記録を記録の Pull Request のコメントに投稿した | `retrospective`(振り返りを通る経路のとき) | 投稿できなかった → 最終工程を終えていないと判定され、課題は閉じない(受け入れ条件 2) | E3(通るとき)、無ければ E2 | -| E5 | `sprint-close.py` が課題ごとに最終工程を終えたかを判定した | 最終工程を担う Skill・まとめのプランの close のステップ・conductor の手打ち | 判定の材料が読めない → 終えたとは読まず、閉じない(受け入れ条件 3)。終えていない → `kept_open` と通っていない工程を返す(受け入れ条件 2) | — (呼ぶ側の順序に頼らない。E4 の前に打たれても閉じない) | -| E6 | 判定を通った課題のボードを `Done` にし、課題を閉じた | E5 | 閉じられなかった → `failed` と打ち直すコマンド(今と同じ) | E5 | -| E7 | 棚卸しを始めた | まとめのプランの refine のステップ・工程表の次の工程 | — | E6 | - -## 用語 - -| 用語 | 意味 | -| --- | --- | -| 最終工程 | 用語集の語。棚卸しの前にその実行で最後に通る工程(前提 2) | -| スプリント課題 | 用語集の語。`sprint-close.py` が閉じる対象にする課題 | -| closing keywords | 用語集の語。Pull Request の本文に `Closes #123` のように書くと、マージ時に GitHub がその課題を閉じる機能 | -| 参照だけの課題 | 用語集の語。スプリントの Pull Request が番号で参照し、スプリント課題に入らない開いた課題 | -| 通過記録 | 用語集の語。進捗記録が実際に書かれた工程を課題ごとに残したファイル。工程に入った時点の記録である | - -## 受け入れ条件 - -各条件の末尾の括弧は、確かめる時期と手段を表す。 - -1. - [ ] `progress-tracking` の「スプリントを閉じる」が、課題を閉じてよい条件として「その課題の最終工程を終えたこと」と、それを判定する材料(未決 1 で決めるもの)を定める。`retrospective`・`release-verification`・`release`・`pr`・`development-workflow` の references は閉じる時点と順序の決まりを写さず、この節を指す(マージ前: `grep` で、閉じる時点の決まりを持つ文書がこの節の 1 か所であることを見る) -2. - [ ] 最終工程を終えていない課題(例: 振り返りを通るモードで振り返りの記録が無い)を含めて `sprint-close.py --record-pr <記録のPR> --issues <番号>` を打つ → `--with-verification` の有無にかかわらず、その課題は閉じず、ボードも `Done` にならず、結果 JSON の `items` に `kept_open` と、終えていない工程の名前を含む `reason` で載る(マージ前: `gh` と判定の材料を差し替えたテスト) -3. - [ ] 最終工程を終えたかを判定する材料が読めない(置き場が無い・読めない・`ok` の結果が無い)課題で同じコマンドを打つ → 終えたとは読まず、その課題は閉じず、`kept_open` か `failed` で理由つきで載り、結果 JSON の `status` は `ok` にならない(#2227 の読む側の規則に従う)(マージ前: テスト) -4. - [ ] 最終工程を終え、リリース後テストの行がすべて合格の課題で `--with-verification` を付けて打つ → 今と同じく受け入れ条件へ `[x]` を付けてボードを `Done` にし、閉じる(退行しない)。`--record-pr 0` と `--record-pr unknown` の今の扱いも変わらない(マージ前: 既存のテストと追加のテスト) -5. - [ ] 振り返りを通るモードで `supervise.py new close` が書くまとめのプランの `steps` の `id` を、`next` のつながりの順に並べる → リリース後テスト(配布の記録があるとき)→ 振り返り → 課題を閉じる → 棚卸しの順になり、`progress-tracking` の「スプリントを閉じる」の表と一致する(マージ前: プランを組んで並びを見るテスト) -6. - [ ] 振り返りを通らないモード・経路(`light`、振り返りを通らない `operation`)のまとめのプランでも、課題を閉じるステップはその経路の最終工程のステップの後、棚卸しのステップの前にある(マージ前: テスト) -7. - [ ] 開発の起点(`.ndf/worktree.json` の `base_branch`、無ければ既定ブランチ)が既定ブランチと同じ構成で、課題の Pull Request を NDF の手順(`pr-steps.py create` / `update`)で作る → でき上がった Pull Request の本文に、マージで課題を閉じる closing keywords(`Closes` / `Fixes` / `Resolves` と活用形)が残らない(#2082 の受け入れ条件 1)(マージ前: 一時のリポジトリの構成で `pr-steps.py` を流すテスト) -8. - [ ] 上と同じ構成で、スプリントの Pull Request(既定ブランチ宛)を NDF の手順で作る → 同じく closing keywords が本文に残らない。その Pull Request だけから成るスプリントで `sprint-close.py --record-pr <記録のPR> --prs <番号> --dry-run` を打つ → 対象の課題が `kept_open`(参照だけの課題)や終了コード 2(集めた課題が 0 件)にならず、閉じる対象(最終工程を終えていれば `would_close`)として判定される(#2082 の受け入れ条件 2・3)(マージ前: テスト) -9. - [ ] 開発の起点が既定ブランチと違う構成(このリポジトリの `develop` 宛)では、今と同じく本文の closing keywords が残り、`sprint-close.py` がそこから課題を集める(退行しない。#2082 の受け入れ条件 4)(マージ前: 既存のテストと追加のテスト) -10. - [ ] 子の 2 件(#2082・#2119)が、それぞれの受け入れ条件を満たして閉じている(子の課題で確かめ、この課題では閉じていることを見る) -11. - [ ] この版の後の最初のスプリントの仕上げで、引継ぎ文書や conductor の手順の並びに関わらず、どの課題もその最終工程の記録より前に閉じない(リリース後: スプリントの課題の `closedAt` と、振り返りの記録のコメントの投稿時刻(振り返りを通らない経路ではその経路の最終工程の記録の時刻)を比べる) - -## 非機能の条件 - -| 大項目 | 条件 | -| --- | --- | -| 運用・保守性 | 閉じる時点の決まりは `progress-tracking` の 1 か所、判定は `sprint-close.py`(とそれが使う `lib`)の 1 か所に置く。まとめのプランと Skill の本文に、閉じてよいかの判定を書き分けない(MVV の Value 6) | -| 移行性 | `sprint-close.py` の閉じる条件が増える(契約の変更)。呼ぶのは同じ版の `plugins/ndf` の中のプラン・Skill の本文だけなので、同じ版で呼ぶ側も直す。利用者の手での移行は要らない。この版より前に工程を通り、判定の材料を持たないまま開いている課題の扱いは未決 2 | - -## 影響 - -| 対象 | 影響 | -| --- | --- | -| 公開インタフェース | 変わる。`sprint-close.py` の閉じる条件・`kept_open` の理由・(足すなら)引数と、`pr-steps.py` が作る本文の closing keywords の扱い。読み手は同じ版の `plugins/ndf` の中だけで、版をまたぐ互換の経路は持たない(`互換なし`) | -| データ | 課題の本文・ボードの形は変えない。判定の材料の置き場を新しく足すかは未決 1 | -| 既存の振る舞い | 今は呼べば閉じていた課題が、最終工程を終えるまで `kept_open` で残る(意図した変化)。既定ブランチ宛の Pull Request の本文から closing keywords が消え、マージで課題が閉じなくなる(意図した変化) | - -## 検証手段 - -| 項目 | 手段 | -| --- | --- | -| テスト | `uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests -q -n 4`(`sprint-close.py` の判定・まとめのプランの並び・`pr-steps.py` の本文の単体テストと、`gh` を差し替えた結合テスト) | -| 静的解析 | CI の既存のチェック(`python3 scripts/check-skill-frontmatter.py`・`python3 plugins/ndf/scripts/instructions-check.py --root .` ほか) | -| 手動確認 | リリース後テストで、この版の後の最初のスプリントの仕上げの結果 JSON と、課題の `closedAt`・振り返りの記録の投稿時刻を見る(受け入れ条件 11)。既定ブランチが起点のリポジトリのスプリントが同じ期間にあれば、課題がマージの時点で OPEN のまま残ったことも見る(#2082 の受け入れ条件 5) | - -## 前提とする取り決め - -| 項目 | 参照先 / 決めたこと | -| --- | --- | -| プロジェクト構造 | 判定のコードは `plugins/ndf/scripts/`(`sprint-close.py` と `lib/`)、プランの組み立ては `supervise_lib/`、決まりの正本は `plugins/ndf/skills/progress-tracking/SKILL.md`。Skill ごとの `scripts/` に同じ役割の関数を置かない(`lib/README.md` の「置いてよいもの・いけないもの」) | -| コーディング規約 | 結果 JSON は `lib/step_result.py` の形(#2227 の後の形)。`.md` の文言を照合するテストは書かない(AGENTS.md の DON'T) | -| テスト戦略 | 判定とプランの並びは単体テスト、`sprint-close.py` と `pr-steps.py` は `gh` を差し替えた結合テスト(`tdd-cycle` の testing-levels) | - -## 境界 - -| 区分 | 内容 | -| --- | --- | -| 常に行う | 既存のテスト全体の実行、正本を写している文書の付け替え、まとめのプランと `sprint-close.py` の同時の更新 | -| 確認してから行う | `sprint-close.py` の閉じる条件・引数の変更と、`pr-steps.py` が作る本文の変更(契約の変更)。承認ゲート 1 の設計と承認ゲート 2 で人が見る | -| 行わない | 他のリポジトリの既存の課題・Pull Request の書き直し、#2227 の結果 JSON の形式の変更、棚卸しの `not planned` の閉じ方の変更 | - -## 未決 - -| 項目 | 誰が決めるか | 期限 | -| --- | --- | --- | -| 1. 最終工程を「終えた」と判定する材料を何にするか。候補: (a) #2227 の結果 JSON(最終工程を担う Skill・ステップの `ok` の結果)、(b) 最終工程の成果物(振り返りの記録のコメント・リリース後テストの記録・配布の記録)が記録の Pull Request にあること、(c) 通過記録に「工程を出た」記録を足す。通過記録はリポジトリの外の手元のファイルで、別の機械・別のセッションからは読めないことを考える | 設計(承認ゲート 1 で利用者が確かめる) | 設計 PR | -| 2. この版より前に工程を通り、判定の材料を持たないまま開いている課題を、この版の `sprint-close.py` がどう扱うか(`kept_open` で残して手で閉じるか、移行の手段を持つか) | 設計 | 設計 PR | -| 3. 既定ブランチ宛の Pull Request の本文に closing keywords が書かれたとき、止めるか参照(`Refs #N`)へ置き換えるか(#2082 は「問わない」としている)と、閉じる課題を集める手段を `--issues` にするか本文の別の記法にするか | 設計 | 設計 PR | -| 4. 最終工程を担う Skill(`retrospective` など)が「スプリントを閉じる」を呼ぶ今の形を残すか、まとめのプランの close のステップだけにするか | 設計 | 設計 PR | diff --git a/issues/issue-2231-design.md b/issues/issue-2231-design.md deleted file mode 100644 index c40bfc4e6..000000000 --- a/issues/issue-2231-design.md +++ /dev/null @@ -1,329 +0,0 @@ -# 配布: Claude Code と codex へすべてのプラグインを配り、agy・kiro は cross 系の相手役としてだけ呼ぶ(#2231) - -## 目的 - -- **何が壊れているか**: NDF とマーケットプレイスのプラグインを 4 つのランタイム(Claude Code・codex・kiro・agy)へ配っている。agy・kiro のためだけに、導入物(`plugins/ndf/dev.agy/`・ndf と playwright-kit と mcp-* 10 個の `dev.kiro/`)・その生成と検査・スモークテスト・リリース後の導入の確認を保ち、agy・kiro だけで起きる不具合(agy の本文の切り詰め #2163、Kiro の導入の確認の版の誤り #1889 など)が増え続ける -- **誰が困るか**: NDF を保守する開発者(agy・kiro の差分を吸収する層を保つ)。agy・kiro が NDF の工程で担うのは cross-review / cross-refactoring の相手役だけで、配った Skill は相手役の経路で使われない -- **直すと何が成り立つか**: 配布先は Claude Code と codex の 2 つになり、どちらにもすべてのプラグインとすべての Skill が今と同じ形で届く。agy・kiro には何も配らず、cross-review / cross-refactoring は今と同じ起動の経路で agy・kiro を相手役として呼ぶ - -## 適用範囲 - -- **働く範囲**: このリポジトリの配布物(`plugins/` の agy・kiro 向けの部分)と、それを組み立てる・確かめるスクリプト・テスト・CI・リリースの宣言(`.ndf/supervise.json`・`.ndf/pace.json`)・文書。利用者の手元では、この変更を含む版から agy・kiro 向けの新しい版が届かなくなる -- **プロジェクトごとに違うもの**: 無し(配布先は NDF の配布物が持ち、利用者のリポジトリの設定では変えない。相手役に使えるランタイムは今どおり `.ndf/runtimes.json` が決める) -- **当たるモード**: `standard` - -## あるべき姿の根拠 - -| 根拠 | 種類 | 何を示すか | -| --- | --- | --- | -| 「claude とcodexのみ、すべてのpluginを配布することとします。agy、kiroは配布せず、cross系で呼ばれるだけ。」(2026-10-31、承認ゲート 1) | 利用者の指示の原文(会話。#2231 の本文の先頭に引用) | 配布先は Claude Code と codex だけで、どちらにもすべてのプラグインを配る。agy・kiro は相手役だけ | -| `plugins/ndf/scripts/lib/launch-cli.sh` は agy を `agy --dangerously-skip-permissions --output-format json …`、kiro を `kiro-cli chat --no-interactive --trust-all-tools …` で起動し、`--agent ndf` もプラグインの導入先も指さない | 実測(コードを読んだ) | 相手役の agy・kiro は、agy・kiro へ配った導入物(`dev.agy/`・`.kiro/agents/ndf.json`)を読まない | -| `plugins/ndf/skills/cross-review/scripts/launch-reviewer.sh` の `render_review_prompt` はレビュー担当の依頼文を Skill を読まずに完結させる。`plugins/ndf/skills/cross-refactoring/scripts/prepare-worktrees.sh` は `REQUIRED_SKILLS`(`refactoring`・`tdd-cycle`・`quality-gates`)を**ホストの導入先**から担当の worktree(kiro は `.kiro/skills`、agy は `.agents/skills`)へ写す | 実測(コードを読んだ) | 相手役が読む手順書はホスト(Claude Code・codex)の導入先から来る。agy・kiro への配布を止めても、相手役の経路は変わらない | -| `plugins/ndf/dev.agy/install-hooks.sh` は `bash ./scripts/<名前>` を導入先(既定 `~/.gemini/config/plugins/ndf`)の絶対パスへ書き換えて `~/.gemini/config/hooks.json` へ差し込む。`plugins/ndf/dev.kiro/install.sh` は利用者の clone の `plugins/ndf/skills/` へ symlink を張り、`.kiro/agents/ndf.json` の hook は clone の `plugins/ndf/scripts/worktree-guard.sh`・`worktree-session.sh`・`wait-notify.py --runtime kiro` を指す | 実測(コードを読んだ) | 既に導入した agy の手元は導入先の写しだけで動き、リポジトリから `dev.agy/` を消しても切れない。kiro の手元は clone の共通のスクリプトを呼ぶため、それを残せば動き続ける(決定 4) | -| ruleset「protect main and develop」の必須のチェックに `runtime-smoke (kiro)`・`runtime-smoke (agy)` がある(`gh api repos/devbasex/ai-plugins/rulesets/22332172`、2026-10-31) | 実測 | スモークの matrix から 2 つを外すと、ruleset を直すまで結果の返らない必須のチェックが残る(決定 6) | - -要求と受け入れ条件は #2231 の本文にある(コピーは `issues/issue-2231-requirements.md`)。この文書は「どう作るか」だけを扱う。受け入れ条件の番号は本文の「受け入れ条件(方針の変更の後)」の 1〜6 を指す。 - -## ドメインモデル - -### コンテキスト - -| コンテキスト | 何の語が 1 つの意味に決まるか | -| --- | --- | -| 配布(`ndf-distribution`) | 配布先・マニフェスト・導入物・リリースの対象ランタイム | -| cross 系の参加(`cross-review-participants`) | ホスト・相手役・担当の worktree へ写す手順書(`REQUIRED_SKILLS`) | - -cross 系の参加が顧客、配布が供給者の関係(顧客 / 供給者)。cross 系は「ホストの導入先に要る Skill」を宣言し、配布はホスト(Claude Code・codex)へその宣言を満たす一覧を配る。相手役のランタイムへの配布は、cross 系の宣言に含まれない。 - -### 集約 - -| 集約 | 持ち主(書き換えてよいもの) | 根 | エンティティ | 値オブジェクト | -| --- | --- | --- | --- | --- | -| 配布先 | マニフェストのファイル名(`plugins/*/manifests/<ランタイム>-skills.txt`)・導入物のディレクトリ(`dev.agy/`・`dev.kiro/`)・`.ndf/supervise.json` の `release.runtimes` | 配布先のランタイムの集合(claude・codex) | — | ランタイムの名前 | -| Claude Code と codex の配布物 | `plugins/ndf/manifests/{claude,codex}-skills.txt`・`.claude-plugin/`・`.codex-plugin/`・`hooks/`・`plugins/playwright-kit/manifests/`。**この変更では変えない** | 各プラグインの `plugin.json` | Skill の参照 | 版数・Skill の数 | -| 相手役の起動経路 | `launch-cli.sh`・`launch-reviewer.sh`・`cross-refactoring/scripts/`・`lib/auth.py`・`lib/runtime_policy.py`。**この変更では変えない** | 起動の共通スクリプト(`launch-cli.sh`) | 担当 | ランタイムの名前・CLI の引数 | -| 必須のチェック | ruleset(利用者が承認ゲート 2 で直す)と `.ndf/project.json` の `required_checks` | ruleset | チェック | チェックの名前 | - -### 不変条件 - -| # | 集約 | 条件 | 破れたときの扱い | -| --- | --- | --- | --- | -| I1 | 配布先 | どのプラグインにも `agy-skills.txt`・`kiro-skills.txt`・`dev.agy/`・`dev.kiro/` が無く、`release.runtimes` は `claude`・`codex` の部分集合である | 新しい pytest(`scripts/tests/test_distribution_runtimes.py`)が落ちる | -| I2 | Claude Code と codex の配布物 | `claude-skills.txt`(49 行)・`codex-skills.txt`(45 行)・各 `.codex-plugin/plugin.json`・`plugins/ndf/hooks/codex.json`・playwright-kit の `claude-skills.txt`・`codex-skills.txt` が変更前と同じである | 実装の PR の差分に現れる。`build-runtime-plugins.sh --check`・`validate-runtime-plugins.sh`・既存の pytest(`test_codex_skill_policies.py` など)が通る | -| I3 | 相手役の起動経路 | agy・kiro を相手役にする起動(`launch-cli.sh` の `agy` / `kiro` の分岐、`prepare-worktrees.sh` の `skill_dir_for`)が変更前と同じに動く | 既存の pytest(`test_lib_launch_cli_runtimes.py`・`cross-review/tests/test_launch_cli_runtimes.py`・`test_launch_agy.py`・`cross-refactoring/tests/test_launch_agy_phases.py`・`test_prepare_worktrees.py`)が落ちる | -| I4 | 配布先 | 既に導入した kiro の手元の hook が呼ぶ共通のスクリプト(`plugins/ndf/scripts/worktree-guard.sh`・`worktree-session.sh`・`wait-notify.py`・`hook.py` の `--runtime kiro`)が残る | 既存の pytest(`worktree/tests/test_guard.py` の `test_kiro_fs_write_is_normalized` など kiro の入力を見るもの)が落ちる | -| I5 | 必須のチェック | ワークフローのジョブと ruleset の必須のチェックが一致する | `required-checks-check`(`scripts/check-required-checks.py`)が落ちる | - -### ドメインイベント - -| # | イベント | 発生元 | 受け手 | -| --- | --- | --- | --- | -| E1 | 配布先を Claude Code と codex に決めた | 利用者の指示(承認ゲート 1、2026-10-31) | 実装(E2・E3) | -| E2 | agy・kiro 向けの一覧・導入物・生成・検査・スモーク・リリースの対象を外した | 実装 | CI(I1・I2・I5) | -| E3 | ruleset の必須のチェックから `runtime-smoke (kiro)`・`runtime-smoke (agy)` を外した | 利用者(承認ゲート 2) | `required-checks-check`(I5) | -| E4 | 新しい版を配った。agy・kiro 向けの版は届かなくなった | リリース | 既に導入した agy・kiro の利用者(README・CHANGELOG の案内) | -| E5 | Claude Code をホストにした cross-review / cross-refactoring で、agy・kiro が相手役として結果を返した | `/ndf:cross-review`・`/ndf:cross-refactoring` | リリース後テスト(受け入れ条件 3) | -| E6 | 直す必要が無くなった open の課題を棚卸しで閉じた | `/ndf:backlog-refinement` | 課題の一覧(「配布を止めると要らなくなる課題」の表を材料にする) | - -### 用語 - -| 用語 | 意味 | 用語集への反映 | -| --- | --- | --- | -| 配布先のランタイム | マーケットプレイスのプラグインを導入できる形で届けるランタイム。この変更の後は Claude Code と codex で、相手役のランタイムとは別に決まる | 追加 | -| 相手役 | cross-review のレビュー担当、cross-refactoring の提案・実装の担当として、ホストから CLI プロセスで起動されるランタイム | なし(#2231 の要求のコミットで追加済み。意味を変えない) | -| マニフェスト | `plugins/ndf/manifests/<ランタイム>-skills.txt`。ランタイムごとに配る Skill の一覧で、配布の唯一の基準(playwright-kit も同じ形の `plugins/playwright-kit/manifests/` を持つ) | なし(同上) | -| ホスト | 収束ループを起動している CLI のランタイム | なし(既存の語。意味を変えない) | - -## 機能一覧 - -| # | 機能 | 誰が使うか | -| --- | --- | --- | -| F1 | Claude Code と codex へ、すべてのプラグインとすべての Skill を今と同じ形で配る(変えない) | Claude Code・codex の利用者 | -| F2 | Claude Code・codex をホストにした cross-review / cross-refactoring で、agy・kiro が相手役を務める(変えない) | Claude Code・codex の利用者 | -| F3 | agy・kiro の導入物が配布物へ戻ったら CI が落とす | NDF の開発者 | -| F4 | 既に agy・kiro へ導入した利用者が、配布の終了を知り、手元を残すか消すかを自分で選べる(README・CHANGELOG の案内) | 既存の agy・kiro の利用者 | - -## 構成要素 - -| 要素 | 責務 | 変え方 | -| --- | --- | --- | -| マニフェスト(`plugins/ndf/manifests/`・`plugins/playwright-kit/manifests/`) | 配布先ごとの Skill の一覧 | `agy-skills.txt`・`kiro-skills.txt`(ndf)と `kiro-skills.txt`(playwright-kit)を消す。claude・codex は変えない(I2) | -| agy の導入物(`plugins/ndf/dev.agy/`) | agy へ渡すプラグインの木 | ディレクトリごと消す(`plugin.json`・`skills/`・`scripts` のリンク・`agents/` 11 本・`hooks.json`・`install-hooks.sh`) | -| kiro の導入物(`plugins/ndf/dev.kiro/`・`plugins/playwright-kit/dev.kiro/`・`plugins/mcp/mcp-*/dev.kiro/` 10 個) | 利用者のリポジトリの `.kiro/` へ配置する | ディレクトリごと消す | -| 生成の手順(`scripts/build-runtime-plugins.sh`・`scripts/lib/agy_agents.py`) | マニフェストから導入物を作る | agy の Skill のリンクとエージェント定義の写し、mcp-* の kiro の installer の生成を外す。`agy_agents.py` を消す。codex の生成(`agents/openai.yaml`・mcp-* の `.codex-plugin`)は変えない | -| 定義の検査(`scripts/validate-runtime-plugins.sh`・`scripts/lib/validate_manifests.py`・`scripts/check-skill-frontmatter.py`・`scripts/check-doc-staleness.py`・`scripts/ci-heavy-skip.py`・`scripts/check-skill-repo-assumptions.py`・`scripts/check-cross-skill-refs.py`) | 版数・Skill 数・一覧の予算・文書の古さの突き合わせ | `dev.agy/plugin.json`・`hooks.json` の検査、Kiro・agy の一覧の予算、ランタイムの名前の表から agy・kiro を外す。相手役の名前(`claude,codex,kiro` の起動の例など)を見る規則は相手役の経路の記述として残す | -| 配布先の検査(新しい pytest `scripts/tests/test_distribution_runtimes.py`) | I1 | 足す | -| ランタイムのスモークテスト(`scripts/runtime-smoke-test.sh`・`scripts/runtime-smoke-latest.py`・`tests/runtime-smoke/`・`.github/workflows/runtime-plugin-smoke*.yml`・`runtime-plugin-authenticated-smoke.yml`) | 導入できることを確かめる | `--runtime` と matrix から `kiro`・`agy` を外す。`Containerfile.{agy,kiro}`・`adapters/{agy,kiro}.sh`・`assertions/assert-kiro-agent.sh` を消し、`cli-versions.env` の `KIRO_*`・`AGY_*` の行を消す。claude・codex の確認は変えない | -| agy・kiro の導入物だけを見るテスト | 生成物の形を固定する | 消す: `scripts/tests/` の `test_agy_agents.py`・`test_agy_distribution.py`・`test_agy_install_hooks.py`・`test_agy_listing_budget.py`・`test_validate_agy_manifest.py`・`test_kiro_installer_project.py`・`test_kiro_mcp_installer_tools.py`・`agy_build_helpers.py`、`plugins/ndf/skills/worktree/tests/test_agy_hooks.py`、`plugins/mcp/mcp-serena/tests/test_serena_lsp_kiro.py`。一部だけ見るもの(`worktree/tests/test_hook_wiring.py`・`plugins/ndf/scripts/tests/test_hook_deadline.py` の `dev.kiro/install.sh` を読む分など)はその部分を外す | -| リリースの宣言と導入の確認(`.ndf/supervise.json`・`.ndf/pace.json`・`plugins/ndf/scripts/release-verification-steps.py`・`plugins/ndf/scripts/release-steps.py`) | リリースの対象ランタイムと版数を持つ箇所 | `release.runtimes` を `["claude", "codex"]` に、`pace.json` の `verify` の `--runtimes` を `claude,codex` にする。`verify_kiro`・`compare_kiro` と `--runtimes` の `kiro` を外し、既定を `claude,codex` にする。版数を持つ箇所から `dev.agy/plugin.json` を外す | -| 必須のチェック(ruleset・`.ndf/project.json` の `required_checks`) | マージを塞ぐチェックの一覧 | `runtime-smoke (kiro)`・`runtime-smoke (agy)` を外す。ruleset は利用者が承認ゲート 2 で直す(決定 6) | -| 既存の kiro の手元が呼ぶ共通のスクリプト(`plugins/ndf/scripts/hook.py`・`hook_lib/worktree.py`・`worktree-guard.sh`・`worktree-session.sh`・`wait-notify.py`) | Claude Code・codex と共有する hook の入口 | 振る舞いは変えない(決定 4)。結線先を `dev.kiro/install.sh`・`dev.agy/hooks.json` と書くコメントだけを「既に導入した手元のため」へ直す | -| 文書(`AGENTS.md`・`CLAUDE.md`・`KIRO.md`・`README.md`・`plugins/ndf/README.md`・`plugins/playwright-kit/README.md`・`plugins/mcp/mcp-*/README.md`・`docs/ndf-plugin-reference.md`・`docs/versioning-and-distribution.md`・`docs/plugin-development-guide.md`・`docs/project-overview.md`・`docs/glossary.md`・`plugins/ndf/skills/AUTHORING.md`・`tests/runtime-smoke/README.md`・`CHANGELOG.md`) | 配布の説明 | 「4 ランタイムへ配る」前提を「Claude Code と codex へ配り、agy・kiro は相手役」へ書き換える。kiro・agy の導入の手順を消す。`KIRO.md` は相手役としての kiro の説明へ縮める(決定 7)。`plugins/ndf/docs/kiro-cli.md` は消す | - -**変えないもの:** 相手役の起動経路(I3)、`plugins/ndf/skills/external-ai/`(`references/cli-agy.md`・`cli-kiro.md` を含む)、`lib/auth.py` の認証確認、`.ndf/runtimes.json` の扱い、`scripts/token-usage.py` の kiro・agy の使用量の読み取り(相手役の使用量)、`.ndf/worktree.json` の `.kiro/`(相手役の設定を置く場所)、Skill の本文と Skill のスクリプトに残るホストとしての kiro・agy の分岐(決定 5)。 - -### 図 - -```mermaid -graph TD - subgraph 配布先 - MC[Claude Code の一覧と配布物] - MX[codex の一覧と配布物] - end - subgraph 消すもの - DA[dev.agy] - DK[各プラグインの dev.kiro] - MA[agy・kiro の一覧] - end - subgraph 相手役の起動経路 - L[launch-cli.sh] - P[prepare-worktrees.sh] - end - H[ホストの導入先] --> P - MC --> H - MX --> H - P --> W[担当の worktree の手順書] - L --> AG[agy CLI] - L --> KI[kiro-cli] - W --> AG - W --> KI - T[配布先の検査] -.落とす.-> DA - T -.落とす.-> DK - T -.落とす.-> MA -``` - -図に含めないもの: 文書・スモークテスト・リリースの宣言(どれも配布先の 2 つだけを書き写す先)と、変えない共通の hook の入口。 - -### 置き場所 - -```text -plugins/ -├── ndf/ -│ ├── manifests/{agy,kiro}-skills.txt # 消す -│ ├── dev.agy/ # 消す -│ ├── dev.kiro/ # 消す -│ ├── docs/kiro-cli.md # 消す -│ └── scripts/release-*.py # kiro と dev.agy の分を外す -├── playwright-kit/ -│ ├── manifests/kiro-skills.txt # 消す -│ └── dev.kiro/ # 消す -└── mcp/mcp-*/dev.kiro/ # 10 個とも消す -scripts/ -├── build-runtime-plugins.sh # agy・kiro の生成を外す -├── lib/agy_agents.py # 消す -├── lib/validate_manifests.py # dev.agy の検査を外す -├── runtime-smoke-test.sh # kiro・agy を外す -├── script-structure-allow/plugins__ndf__dev.kiro__install.sh--lines.json # 消す -└── tests/test_distribution_runtimes.py # 新設(I1) -tests/runtime-smoke/ # agy・kiro の像・adapter・確認を消す -.github/workflows/runtime-plugin-*.yml # matrix から kiro・agy を外す -.ndf/{supervise,pace,project}.json # kiro・agy を外す -``` - -## 処理の流れ - -### 相手役として起動されるとき(変えない) - -```mermaid -sequenceDiagram - participant H as ホスト(Claude Code / codex) - participant P as 準備(prepare-worktrees.sh) - participant L as 起動の共通スクリプト(launch-cli.sh) - participant R as 相手役(agy・kiro) - H->>P: cross-refactoring の初期化 - P->>P: ホストの導入先から REQUIRED_SKILLS を担当の worktree へ写す - H->>L: 依頼文と worktree を渡す - L->>R: CLI プロセスで起動(agy は --add-dir、kiro は --agent を付けない) - R->>R: 依頼文と worktree の中の手順書だけを読む - R-->>H: 結果ファイル -``` - -**agy・kiro へ配った導入物は、この流れのどこにも現れない。** そのため配布を止めても相手役の振る舞いは変わらない(受け入れ条件 3 は既存の pytest とリリース後テストで確かめる)。 - -### 配布物を組み立てて確かめる流れ - -```mermaid -graph LR - M[claude・codex のマニフェスト] --> B[生成の手順] - B --> C[codex の openai.yaml と mcp-* の .codex-plugin] - C --> V[定義の検査] - D[配布先の検査] --> V - C --> S[スモーク claude・codex] - R[release.runtimes claude・codex] --> VI[リリース後の導入の確認] -``` - -実装の順序: 導入物と一覧の削除 → 生成の手順(`--check` が通る形へ) → 定義の検査と配布先の検査 → テストの削除と縮小 → スモークと CI → リリースの宣言と導入の確認 → 文書と CHANGELOG。ruleset の変更は承認ゲート 2 で利用者が行い、その後に `required-checks-check` が通る。 - -## 非機能の実現方式 - -| 大項目 | 要求の条件 | 実現方式 | 確かめ方 | -| --- | --- | --- | --- | -| 運用・保守性 | agy・kiro のためだけに保つものを減らす | 導入物・生成・検査・スモーク・テストを消す | 実装の PR に、消したファイル数と行数(`git diff --shortstat develop`)、CI のスモークのジョブ数(4 → 2)を書く | -| 移行性 | 既に agy・kiro へ導入した利用者の手元を消さない | 決定 4。手元が呼ぶ共通のスクリプトを残し、README・CHANGELOG に配布の終了と消し方を書く | 実装で、一時の HOME・一時のリポジトリに変更前の版を agy・kiro へ入れ、変更後の clone で kiro の hook が動くことと、README の消し方のコマンドを打って結果を確かめる | -| システム環境 | 相手役に使う CLI の版の下限は変えない | `launch-cli.sh` の起動の形と `lib/auth.py` を変えない | 差分に現れないことを見る | - -### 既に導入した利用者の手元 - -| ランタイム | 手元に残るもの | この変更の後どうなるか | README に書く案内 | -| --- | --- | --- | --- | -| agy | `~/.gemini/config/plugins/ndf`(導入の写し)と `~/.gemini/config/hooks.json` の `ndf-worktree` の項目 | 写しの絶対パスを指すため、そのまま動く。新しい版は届かない(`agy plugin install /plugins/ndf/dev.agy` は新しい clone では対象が無く失敗する) | 配布の終了と最後の版。消すときは、写しが残るうちに最後の版のタグの `install-hooks.sh --uninstall` で `hooks.json` の項目を外し、`agy plugin uninstall ndf` を打つ | -| kiro | `.kiro/skills/` の symlink(利用者の clone を指す)・`.kiro/steering/ndf-policies.md`・`.kiro/prompts/` の 6 本・`.kiro/agents/ndf.json`(hook が clone の共通のスクリプトを指す)と、mcp-* の installer が書いた設定 | clone を新しい版へ進めても、Skill の実体と共通のスクリプトが残るためそのまま動く。installer は無くなり、打ち直すと「ファイルが無い」で止まる | 配布の終了と最後の版。残したい利用者は clone を最後の版のタグへ固定できる。消すときのパスとコマンド(`ndf.json` を既定のエージェントにした利用者は `kiro-cli agent set-default kiro_default` で戻してから消す) | - -## 決定の記録 - -### 決定 1: 配布先を利用者の指示どおり Claude Code と codex に限るため、agy・kiro 向けの一覧・導入物・リリースの対象をすべて外す - -`plugins/ndf/manifests/agy-skills.txt`・`kiro-skills.txt`、`plugins/playwright-kit/manifests/kiro-skills.txt`、`plugins/ndf/dev.agy/`、ndf・playwright-kit・mcp-* 10 個の `dev.kiro/` を消し、それを作る・確かめる生成・検査・スモーク・テストと、`.ndf/supervise.json` の `release.runtimes`・`.ndf/pace.json` の導入の確認から kiro を外す(「構成要素」の表)。 - -前の版のこの設計は「codex・agy・kiro へ cross 系をホストとして回せる 8 本だけを配る」(前の決定 1)と「codex・agy・kiro をホストにした cross 系を保証の内に残す」(前の決定 2)を推した。利用者は承認ゲート 1 で次の 2 点を覆した。 - -- **8 本を配る案は採らない。** 8 本は agy・kiro をホストとして回すための一覧だった。利用者は agy・kiro を「cross系で呼ばれるだけ」とし、ホストとしての使い方を残さない。相手役に要る Skill は 0 本である(「あるべき姿の根拠」の 2・3 行目)ため、agy・kiro に配るものは無い -- **codex も絞る案は採らない。** 利用者は codex を Claude Code と同じ配布先にし、すべてのプラグインを配るとした(決定 2) -- **一覧を空のファイルにして導入物の枠を残す案も採らない。** 中身の無い導入物のために生成・検査・スモークを保つことになり、減らしたい費用が残る - -この変更は配布物の取得元を変える操作(P1)に当たる。利用者の指示(承認ゲート 1)と承認ゲート 2 の承認で行う。要求の前の版の未決 1(配る Skill の一覧)・未決 2(ホストの扱い)は、この決定で解消する。 - -根拠: 利用者の指示(2026-10-31)/ P1 / Value 1・Value 6(MVV 版 3) - -### 決定 2: codex の利用者が今と同じものを受け取るため、codex の配布物は変えない - -`codex-skills.txt`(45 行)、`plugins/ndf/.codex-plugin/plugin.json`、`plugins/ndf/hooks/codex.json`(開始時のモデル学習の停止 `training-optout.py` を含む)、codex 向けの生成物(`skills/*/agents/openai.yaml`)、mcp-* 10 個の `.codex-plugin/`、playwright-kit の `codex-skills.txt` を変えない(I2)。前の版の設計が持っていた例外(`cherry-pick-pr`・`deploy` の `openai.yaml` の削除)は無くなる。 - -codex のマニフェストを Claude Code の 49 行へ揃える案は採らない。利用者の指示は「配布は縮めない」で、増やすことは求めていない。差の 4 本(`install-wrapper`・`official-skills-autoloader`・`restart`・`statusline`)は今も codex へ配っていない Skill で、この変更の範囲に無い。 - -根拠: 利用者の指示(2026-10-31)/ 判断の範囲は目の前の変更に限る(共通原則) - -### 決定 3: 相手役の結果を変えないため、agy・kiro を呼ぶ起動経路はコードも引数も変えない - -`plugins/ndf/scripts/lib/launch-cli.sh`、`plugins/ndf/skills/cross-review/scripts/launch-reviewer.sh`、`plugins/ndf/skills/cross-refactoring/scripts/`(`launch-cli.sh`・`prepare-worktrees.sh`・`refactor_lib/`)、`lib/auth.py`、`lib/runtime_policy.py`、`external-ai` の Skill を触らない(I3)。cross-review の既定の母集合(claude・codex・kiro とホスト、agy は `--include agy`)も変えない。 - -相手役の名前を見る検査の規則(`check-skill-repo-assumptions.py` の `claude,codex,kiro` など)は、起動の例として残るものがあるため、検査を直すときに相手役の経路の記述を落とさないかを個別に見る。 - -根拠: 受け入れ条件 3 / Value 2(MVV 版 3) - -### 決定 4: 既に導入した agy・kiro の利用者の手元を壊さないため、手元を消す操作をせず、手元が呼ぶ共通のスクリプトを残し、配布の終了と消し方を案内する - -扱いは「放置して動かし続け、案内する」にする。 - -- **消さない。** installer・スクリプト・リリースの工程のどれも、利用者の `~/.gemini/`・`.kiro/` に触れない(要求の前提・C6) -- **動かし続ける。** agy の手元は導入の写しだけで動くため、何もしなくても動く。kiro の手元の hook は clone の `plugins/ndf/scripts/worktree-guard.sh`・`worktree-session.sh`・`wait-notify.py --runtime kiro` を呼ぶ。これらは Claude Code・codex と共有するため残り、`hook.py`・`hook_lib/worktree.py`・`wait-notify.py` の kiro の分岐も残す(I4) -- **案内する。** `plugins/ndf/README.md` と `CHANGELOG.md` に、agy・kiro への配布を終えたこと・最後に配った版(この変更を含む版の 1 つ前)・手元を残すときの固定のしかた・消すときのコマンド(「既に導入した利用者の手元」の表)を書く。コマンドは書く前に一時の HOME で打って確かめる - -共通のスクリプトの kiro の分岐を消す案は採らない。clone を進めた kiro の利用者で、プロンプトを送るたびに hook が失敗する。手元を消す移行スクリプトを配る案も採らない。利用者の手元を消す操作で、配布を止める版から実行の手段(installer)も無くなる。分岐をいつ消すかは決めず、棚卸しで利用の実態を見て決める。 - -根拠: C6 / 上位の原則(人を守る)/ Value 2(MVV 版 3) - -### 決定 5: 変更の範囲を配布物に限るため、Skill の本文と Skill のスクリプトに残るホストとしての kiro・agy の分岐はこの変更で消さない - -例: `plugins/mcp/mcp-redash/scripts/redash-mcp-config.js` の `syncKiroAgent`、`statusline`・`worktree`・`official-skills-autoloader` の本文の Kiro の記述、cross-review の `docs/01-state-and-review.md` のホストの導入先の候補(`.kiro/skills`・`~/.gemini/config/plugins/ndf`)。どれも Claude Code・codex へ配る Skill の中にあり、agy・kiro へ配らなくなった後は使われない。 - -一緒に消す案は採らない。相手役としての kiro・agy の記述(担当の worktree の `.kiro/skills`、`.agents/skills`)と同じファイルに並び、取り違えると受け入れ条件 3 を壊す。Skill の本文の変更は Claude Code・codex の利用者に届く変更でもあり、配布先を絞るこの変更と分けて確かめる方が戻しやすい。残る分岐は「配布を止めると要らなくなる課題」の #2058 とあわせて棚卸しで扱う。 - -根拠: 判断の範囲は目の前の変更に限る(共通原則)/ Value 1(MVV 版 3) - -### 決定 6: マージを塞ぐチェックを実在するジョブと一致させるため、ruleset の必須のチェックから `runtime-smoke (kiro)`・`runtime-smoke (agy)` を外す操作は承認ゲート 2 で利用者が行う - -実装の PR はスモークの matrix と `.ndf/project.json` の `required_checks` から 2 つを外す。ruleset は利用者が承認ゲート 2 で直す(`scripts/required-checks-allow.json` の `awaiting` の 2 件と同じ扱い)。直すまでは、実装の PR で 2 つのチェックの結果が返らず、`required-checks-check` は ruleset とジョブの食い違いを出す。 - -matrix に `kiro`・`agy` を残して何もしないジョブにする案は採らない。確かめていないものを通ったと見せる。ruleset を実装の担当が直す案も採らない。マージできる条件を変えるリポジトリの設定の変更で、適用の前に利用者の確認を経る。 - -根拠: Value 2(承認を 2 回に寄せる)/ C2(誰が何をできるかが変わる)(MVV 版 3) - -### 決定 7: 指示書の置き場を保つため、`KIRO.md` は消さずに相手役としての kiro の説明へ縮め、`plugins/ndf/docs/kiro-cli.md` は消す - -`KIRO.md` は指示書のチェック(`.ndf/instructions.json`)が読む 3 つの指示書の 1 つで、受け入れ条件 4 が「2 ランタイム配布+相手役 2 つの構成を書く」対象に挙げる。導入の手順を消し、kiro は配布先ではなく相手役として起動されること・起動の形の正本(`external-ai` の `references/cli-kiro.md`)を書く。`plugins/ndf/docs/kiro-cli.md` は kiro へ導入する利用者向けの手引きで、読み手がいなくなるため消し、参照を張り替える。 - -`KIRO.md` を消す案は採らない。指示書のチェックの設定と #1968 の扱いまで変えることになり、範囲を広げる。 - -根拠: 受け入れ条件 4 / Value 7(正本は 1 か所)(MVV 版 3) - -### 決定 8: 配布先の正しさを機械で保つため、agy・kiro の導入物が戻ったら落ちる pytest を置き、agy・kiro の導入物だけを見るテストは消す - -`scripts/tests/test_distribution_runtimes.py` は、`plugins/` の下に `agy-skills.txt`・`kiro-skills.txt`・`dev.agy/`・`dev.kiro/` が無いこと、`.ndf/supervise.json` の `release.runtimes` が `claude`・`codex` の部分集合であることを確かめる(I1)。消すテストは「構成要素」の表のとおりで、消したものの形を固定するテストは見る対象が無くなる。 - -`build-runtime-plugins.sh --check` だけに任せる案は採らない。生成の手順から agy・kiro の部分を消すと、手で足した `dev.kiro/` を見る者がいなくなる。 - -根拠: Value 4 / Value 3(MVV 版 3) - -## テスト設計 - -| 受け入れ条件・不変条件 | どの振る舞いで縛るか | どう壊したら落ちるべきか | -| --- | --- | --- | -| 受け入れ条件 1・I1 | `test_distribution_runtimes.py` が導入物と一覧の不在と `release.runtimes` を確かめる。`build-runtime-plugins.sh --check`・`validate-runtime-plugins.sh` が agy・kiro の生成物を求めずに通る | `plugins/mcp/mcp-notion/dev.kiro/install.sh` を 1 つ戻すと落ちる。`release.runtimes` に `kiro` を足すと落ちる | -| 受け入れ条件 2・I2 | `git diff develop -- plugins/ndf/manifests/codex-skills.txt plugins/*/.codex-plugin plugins/mcp/*/.codex-plugin plugins/ndf/hooks/codex.json plugins/playwright-kit/manifests/codex-skills.txt` が空で、`build-runtime-plugins.sh --check` が通る。リリース後に `release-verification-steps.py verify-install --runtimes claude,codex` が通る | codex の生成を消すと `--check` か codex のスモークが落ちる | -| 受け入れ条件 3・I3 | 既存の pytest(I3 の行の 5 本)が変更前と同じに通る。リリース後テストで、新しい版を入れた環境から `/ndf:cross-review --include agy` と `/ndf:cross-refactoring ` を 1 回ずつ回し、agy・kiro の結果ファイルが揃う | `launch-cli.sh` の `kiro` の分岐を消すと既存の pytest が落ちる。NO_RESULT が出たら失敗として記録する | -| I4 | `worktree/tests/test_guard.py` の kiro の入力のテストが通る。installer を読むテスト(`test_hook_wiring.py`・`scripts/tests/test_hook_deadline.py` の `dev.kiro/install.sh` の分)は外す | `hook.py` の `RUNTIMES` から `kiro` を消すと落ちる | -| 受け入れ条件 4 | `check-markdown-links.py --root .`・`instructions-check.py --root .`・`check-doc-staleness.py` が通る。文言を照合するテストは書かない(`AGENTS.md`) | 消した `plugins/ndf/docs/kiro-cli.md` への参照を残すとリンク検査が落ちる | -| 受け入れ条件 5・I5 | スモークの matrix が `[claude, codex]` で通り、ruleset を直した後に `required-checks-check` が通る | matrix に `kiro` を残すと、消した adapter が無くて落ちる | -| 受け入れ条件 6 | 「配布を止めると要らなくなる課題」の表が実装の PR の本文に写る | — | -| 退行 | `uv run --frozen --project . --all-extras pytest . -q -n 4` と `claude plugin validate .` が通る | — | - -## 配布を止めると要らなくなる課題 - -受け入れ条件 6 の材料である。`gh issue list --state open --search "agy in:title,body"`(`kiro`・`Antigravity` も同じ)で拾った 31 件から選んだ。閉じるかは棚卸し(`/ndf:backlog-refinement`)が決める。実装の PR では閉じない。 - -| 課題 | 扱いの案 | 理由 | -| --- | --- | --- | -| #2163 agy が NDF の Skill 5 本の本文を先頭 24000 バイトで切る | 閉じる | agy へ Skill を配らない。相手役の agy は担当の worktree の手順書を依頼文の明示パスで読み、Skill として読み込まない | -| #1889 verify-install の Kiro は `--plugins` を見ず ndf の版を読む | 閉じる | `release-verification-steps.py` の `verify_kiro` を消す。関連の #1756 は kiro に限らないため残る | -| #2058 mcp-redash の設定スクリプトが Kiro の `default.json` を tools 無しで作る | 閉じる | Kiro へ mcp-redash を配らない。`syncKiroAgent` の残りを消すかは決定 5 のとおり棚卸しで決める | -| #2115 ndf-plugin-reference を 4 ランタイムの今の構成に揃える | 閉じる候補 | 受け入れ条件 4 で `docs/ndf-plugin-reference.md` を 2 ランタイムの構成へ書き直す。残る食い違いがあるかを棚卸しで見る | - -残すもの(agy・kiro に触れるが、相手役の経路か配布と関わらない): #1603・#1981(相手役の agy の出力の形とモデル)、#1735・#2093(相手役の起動を含むテストの揺れ)、#1960(相手役へ渡す手順書の量)、#1968(`KIRO.md` は指示書として残る。決定 7)、#690(リポジトリの description と topics は 4 ランタイムを前提にしており、閉じずに中身を 2 ランタイムへ直す)、#694・#715・#1142・#1571・#1957・#1979・#1983・#2028・#2049・#2071・#2164・#2176・#2205・#2228・#2288・#158・#2168(本文で agy・kiro に触れるが主題が別)、#2296(MVV の改訂)。 - -## 設計の結果 - -| 課題 | 扱い | 取り込み先 | 触るファイル | -| --- | --- | --- | --- | -| #2231 | 実装する | — | `plugins/ndf/manifests/`、`plugins/ndf/dev.agy/`、`plugins/ndf/dev.kiro/`、`plugins/ndf/docs/kiro-cli.md`、`plugins/ndf/scripts/release-verification-steps.py`、`plugins/ndf/scripts/release-steps.py`、`plugins/ndf/scripts/hook_lib/worktree.py`、`plugins/ndf/scripts/progress-record.sh`、`plugins/ndf/skills/worktree/tests/`、`plugins/ndf/skills/release-verification/SKILL.md`、`plugins/ndf/skills/AUTHORING.md`、`plugins/ndf/README.md`、`plugins/playwright-kit/manifests/`、`plugins/playwright-kit/dev.kiro/`、`plugins/playwright-kit/README.md`、`plugins/mcp/`、`scripts/build-runtime-plugins.sh`、`scripts/validate-runtime-plugins.sh`、`scripts/lib/`、`scripts/check-skill-frontmatter.py`、`scripts/check-doc-staleness.py`、`scripts/ci-heavy-skip.py`、`scripts/check-skill-repo-assumptions.py`、`scripts/check-cross-skill-refs.py`、`scripts/runtime-smoke-test.sh`、`scripts/runtime-smoke-latest.py`、`scripts/script-structure-allow/`、`scripts/tests/`、`tests/runtime-smoke/`、`.github/workflows/`、`.ndf/supervise.json`、`.ndf/pace.json`、`.ndf/project.json`、`AGENTS.md`、`CLAUDE.md`、`KIRO.md`、`README.md`、`CHANGELOG.md`、`docs/ndf-plugin-reference.md`、`docs/versioning-and-distribution.md`、`docs/plugin-development-guide.md`、`docs/project-overview.md`、`docs/glossary.md` | - -## 未確認のまま残ること - -| 項目 | 内容 | -| --- | --- | -| プロジェクト MVV との食い違い | Mission(Claude Code / Codex / Kiro / agy のどれを使うチームにも開発工程を届ける)が、2 ランタイムへの配布と食い違う。改訂は #2296 で扱う。利用者の指示は MVV より上位のため、この設計は改訂を待たずに進める | -| ruleset の必須のチェックの変更(決定 6) | 承認ゲート 2 で利用者が `runtime-smoke (kiro)`・`runtime-smoke (agy)` を外すまで、実装の PR の 2 つのチェックは結果を返さない | -| 既に導入した利用者の手元が動き続けるか(決定 4) | コードを読んで判断した。agy の写しで hook が動き続けること、clone を進めた kiro で hook が動き続けること、README の消し方のコマンドは、実装で一時の HOME と一時のリポジトリに変更前の版を入れて確かめる | -| 相手役が今と同じ結果を返すか(受け入れ条件 3) | 起動の経路をコードで読み、配布物を使わないと判断した。実物はリリース後テストで確かめる | -| ホストとしての kiro・agy の分岐の扱い(決定 5) | Skill の本文とスクリプトに残る分岐を、いつ・どの課題で消すかは決めていない。棚卸しで決める | -| 確定仕様の記述 | `docs/specifications/`(`ndf-knowledge-and-kiro.md` など)の kiro・agy の導入の記述は、リリース後の確定仕様化で直す。この変更の実装では触らない | diff --git a/issues/issue-2231-requirements.md b/issues/issue-2231-requirements.md deleted file mode 100644 index 514cabcce..000000000 --- a/issues/issue-2231-requirements.md +++ /dev/null @@ -1,175 +0,0 @@ -# #2231: 配布を Claude Code と codex だけにし(すべてのプラグイン)、agy・kiro へは配らず cross 系の相手役だけにする - -正は課題の本文(#2231)で、この文書はその写しである。`spec-copy.py write` で作り直す。手で直さない。 - -## 方針の変更(2026-10-31 夜、承認ゲート 1 で利用者が指示) - -> claude とcodexのみ、すべてのpluginを配布することとします。agy、kiroは配布せず、cross系で呼ばれるだけ。 - -(書き手: 利用者、日付: 2026-10-31。会話の原文) - -- **Claude Code と codex**: マーケットプレイスのすべてのプラグイン(ndf・playwright-kit・mcp-*)を、すべての Skill で配る。codex の配布は縮めない -- **agy と kiro**: 何も配らない(`plugins/ndf/manifests/agy-skills.txt`・`kiro-skills.txt`、`dev.agy/`・各プラグインの `dev.kiro/` の導入物、`release.runtimes` の kiro を外す)。cross-review / cross-refactoring から相手役の CLI として呼ばれる経路だけを保つ -- 下の「依頼(原文)」と受け入れ条件のうち、codex に配布を絞る部分はこの変更で置き換わる。プロジェクト MVV の Mission(4 ランタイム)の改訂は別の課題で扱う - -## 受け入れ条件(方針の変更の後) - -- [ ] 1. `agy-skills.txt`・`kiro-skills.txt` と agy・kiro 向けの導入物(`dev.agy/`、ndf・playwright-kit・mcp-* の `dev.kiro/`)が配布物から無くなり、`release` の対象ランタイムが claude と codex だけになる(マージ前にテストとビルドで確かめる) -- [ ] 2. codex へ配る Skill とプラグインは変更前と同じ(すべて)である(マージ前に manifests とビルドで確かめる) -- [ ] 3. agy・kiro を相手役にした cross-review と cross-refactoring の起動経路(`launch-cli.sh`・`launch-reviewer.sh`)が変わらず通る(マージ前にテスト、リリース後に実物で確かめる) -- [ ] 4. AGENTS.md・CLAUDE.md・KIRO.md・README・`docs/ndf-plugin-reference.md`・`docs/versioning-and-distribution.md`・`docs/plugin-development-guide.md` が 2 ランタイム配布+相手役 2 つの構成を書く(マージ前にリンク検査と指示書のチェックで確かめる) -- [ ] 5. ランタイムのスモークテストと CI から agy・kiro の導入の検査が外れ、codex の検査は残る(マージ前に CI で確かめる) -- [ ] 6. 配布をやめると直す必要が無くなる agy・kiro だけの open の課題の一覧を設計に載せる(閉じるのは棚卸し) - ---- - -## 依頼(原文) - -> **codex・agy・kiro へは、cross-review / cross-refactoring に要る Skill 以外を配布しない。** - -(書き手: 利用者(起票者が「決めたこと(2026-10-31)」として本文へ引用した文。会話の原文は確かめていない)、日付: 2026-10-31) - -> ## 何が困るか -> -> NDF は Claude Code・Codex・Kiro CLI・agy の 4 つのランタイムへ、ほぼ同じ Skill を配っている(`plugins/ndf/manifests/*-skills.txt`)。同じ機能を 4 通りに保つ費用がかかり、ランタイムごとの差分を吸収する層・スモークテスト・不具合(agy の本文の切り詰め #2163 など)が増え続ける。 -> -> Codex・agy・kiro が NDF の工程で担っているのは、cross-review と cross-refactoring の相手役である。工程の本体(supervise・relay・承認ゲート・hook)は Claude Code で動かす。 -> -> ## 直すもの -> -> - `plugins/ndf/manifests/codex-skills.txt`・`agy-skills.txt`・`kiro-skills.txt` を、cross-review / cross-refactoring に要る Skill だけにする(要る Skill の一覧は設計で決める) -> - `dev.agy/`・`dev.kiro/` の agents・hook・steering のうち、その 2 つに要らないものを外す -> - AGENTS.md の「4 ランタイム共通」の前提、各ランタイムの README、`docs/ndf-plugin-reference.md`、`docs/versioning-and-distribution.md` を新しい配布に合わせる -> - ランタイムのスモークテストを、配る Skill に合わせて絞る -> -> ## 受け入れ条件 -> -> - 3 つのマニフェストに、cross-review / cross-refactoring に要らない Skill が無い -> - 絞った後も、codex・agy・kiro を相手役にした cross-review と cross-refactoring が通る -> - 配布を絞ると直す必要が無くなる open の課題(agy・kiro・codex だけで起きる不具合)を棚卸しで閉じる - -(書き手: 起票者、日付: 2026-10-31。上の引用以外は利用者の指示の原文として扱わない) - -## 起票者の推定 - -| # | 条件 | 推した出所 | この要求での扱い | -| --- | --- | --- | --- | -| S1 | codex・agy・kiro が NDF の工程で担うのは cross-review / cross-refactoring の**相手役**だけで、工程の本体(supervise・relay・承認ゲート・hook)は Claude Code で動かす | 本文「何が困るか」の 2 段落目 | 前提 1。受け入れ条件 1・2 の「要る」の判定基準にする | -| S2 | 要る Skill の一覧は設計で決める | 本文「直すもの」の 1 行目 | 未決 1(設計で決め、承認ゲート 1 で利用者が確かめる) | -| S3 | `dev.agy/`・`dev.kiro/` の agents・hook・steering も、2 つに要らないものを外す(利用者の文は「Skill」だけを言う) | 本文「直すもの」の 2 行目 | 受け入れ条件 3・4 | -| S4 | AGENTS.md・各ランタイムの README・`docs/ndf-plugin-reference.md`・`docs/versioning-and-distribution.md` を新しい配布に合わせる | 本文「直すもの」の 3 行目、方針メモ「4 ランタイム共通の前提(AGENTS.md)を変える」 | 受け入れ条件 6 | -| S5 | ランタイムのスモークテストを配る Skill に合わせて絞る | 本文「直すもの」の 4 行目 | 受け入れ条件 7 | -| S6 | 配布を絞ると直す必要が無くなる open の課題を棚卸しで閉じる | 本文「受け入れ条件」の 3 行目 | 受け入れ条件 9。閉じるのは棚卸しの工程で行い、実装の PR では閉じない | -| S7 | codex・agy・kiro を**ホスト**にして cross-review / cross-refactoring を起動する使い方(`--host codex` など)は残さない | 起票者(この要求を書いた AI)が S1 から推した。本文には書かれていない | 前提 2・未決 2。承認ゲート 1 で利用者が確かめる | - -## 目的 - -- codex・agy・kiro へ配る NDF を、cross-review / cross-refactoring の相手役に要るものだけにし、同じ機能を 4 通りに保つ費用(ランタイムごとの差分を吸収する層・スモークテスト・ランタイムだけで起きる不具合)を減らす -- 絞った後も、Claude Code をホストにした cross-review / cross-refactoring で codex・agy・kiro が相手役として今と同じ結果を返す - -## 前提 - -- 前提 1: Claude Code 以外のランタイムが NDF の工程で担う役割は、cross-review のレビュー担当と cross-refactoring の提案・実装の担当(相手役)だけである(S1) -- 前提 2: cross-review / cross-refactoring のホスト(収束ループを起動する CLI)は Claude Code に限る。codex・agy・kiro をホストにする使い方は、この変更の後は保証しない(S7。誤っても、配る Skill の一覧へ行を足せば戻せる) -- 前提 3: 相手役が読む手順は、ホストの側が担当のworktreeへ置くか、起動の依頼文に直接書く。今の実装では、cross-review のレビュー担当の依頼文は Skill を読まずに完結し(`plugins/ndf/skills/cross-review/scripts/launch-reviewer.sh` の `render_review_prompt`)、cross-refactoring は `refactoring`・`tdd-cycle`・`quality-gates` をホストの導入先から担当のworktreeへ写す(`plugins/ndf/skills/cross-refactoring/scripts/prepare-worktrees.sh`・`refactor_lib/vocabulary.py` の `REQUIRED_SKILLS`)。相手役のランタイムに配った Skill に頼る経路が他に無いことは、設計で確かめる -- 前提 4: Claude Code へ配る Skill(`plugins/ndf/manifests/claude-skills.txt`)は変えない -- 前提 5: 利用者の手元に既に入っている codex・agy・kiro 向けの Skill を、こちらから消す操作はしない。配布物から消えた Skill が手元に残るかは各ランタイムの導入の振る舞いに従い、その扱いを利用者向けの文書に書く - -## 対象範囲 - -含む: -- `plugins/ndf/manifests/codex-skills.txt`・`agy-skills.txt`・`kiro-skills.txt` の中身 -- `plugins/ndf/dev.agy/`・`plugins/ndf/dev.kiro/` のエージェント定義・hook・steering・プロンプトのうち、相手役に要らないもの -- 配布物を組み立てる・確かめるスクリプトとテスト(マニフェストを読むもの、ランタイムのスモークテスト)を、新しい配布に合わせる -- `AGENTS.md` の「4 ランタイム共通」の記述、各ランタイムの README、`docs/ndf-plugin-reference.md`、`docs/versioning-and-distribution.md` -- 配布を絞ると直す必要が無くなる open の課題の一覧(棚卸しへ渡す材料) - -含まない: -- Claude Code へ配る Skill・エージェント・hook の変更 -- cross-review / cross-refactoring 自体の振る舞いの変更(参加者プール・輪番・収束の規則) -- playwright-kit・mcp-* プラグインの配布 -- 一覧にした open の課題を実装の PR で閉じること(閉じるのは棚卸し) -- 利用者の手元の導入済みの Skill を消す操作 - -## ドメインイベント - -| # | イベント | 引き金 | 失敗したとき | 順序の前提 | -| --- | --- | --- | --- | --- | -| E1 | 相手役に要る Skill の一覧を決めた | 設計 | 一覧に漏れがあると E5・E6 で相手役が手順を読めない。受け入れ条件 2 のテストが落とす | — | -| E2 | 3 つのマニフェストを一覧に合わせて絞った | 実装 | 要らない Skill が残る・要る Skill が欠ける。受け入れ条件 1・2 のテストが落とす | E1 | -| E3 | `dev.agy/`・`dev.kiro/` から要らないエージェント・hook・steering を外した | 実装 | 外したものを導入の手順・hook の設定が参照したまま残り、導入が失敗する。受け入れ条件 3・4・5 が落とす | E1 | -| E4 | 利用者が新しい版を codex・agy・kiro へ導入した | リリースと利用者の更新 | 導入の検証(`claude plugin validate .`・ランタイムのスモークテスト)が落ちる | E2・E3 | -| E5 | Claude Code をホストにした cross-review で、codex・agy・kiro がレビュー担当として結果ファイルを返した | `/ndf:cross-review` | 結果ファイルが無い(NO_RESULT)。受け入れ条件 8 の確認で見る | E4 | -| E6 | Claude Code をホストにした cross-refactoring で、codex・agy・kiro が提案・実装の担当として結果を返した | `/ndf:cross-refactoring` | 手順書(`refactoring` など)がworktreeに無く、提案が語彙外で全件降格する。受け入れ条件 8 の確認で見る | E4 | -| E7 | 直す必要が無くなった open の課題を棚卸しで閉じた | `/ndf:backlog-refinement` | 一覧の漏れ。受け入れ条件 9 | E4 | - -## 用語 - -| 用語 | 意味 | -| --- | --- | -| 相手役 | cross-review のレビュー担当、cross-refactoring の提案・実装の担当として、ホストから CLI プロセスで起動されるランタイム | -| ホスト | cross-review / cross-refactoring の収束ループを起動し、修正(`/ndf:fix`)と記録を行う CLI | -| マニフェスト | `plugins/ndf/manifests/<ランタイム>-skills.txt`。ランタイムごとに配る Skill の一覧 | - -## 受け入れ条件 - -- [ ] 1. `plugins/ndf/manifests/codex-skills.txt`・`agy-skills.txt`・`kiro-skills.txt` のどの行も、設計で決めた「相手役に要る Skill の一覧」に含まれる。一覧に無い Skill がマニフェストにあると落ちる検査が CI で動く -- [ ] 2. 相手役が起動時に読む Skill(cross-refactoring の `REQUIRED_SKILLS` など、設計で洗い出したもの)が、ホストの導入先からworktreeへ写せる。欠けると落ちる検査が CI で動く -- [ ] 3. `plugins/ndf/dev.agy/` の配布物(エージェント定義・`hooks.json`・`skills/`・`scripts/`)に、相手役に要らないものが無い。何を残したかと理由は設計文書に表で残る -- [ ] 4. `plugins/ndf/dev.kiro/install.sh` が生成するもの(`.kiro/skills/`・`.kiro/steering/`・`.kiro/agents/ndf.json`)と `dev.kiro/` のプロンプトに、相手役に要らないものが無い -- [ ] 5. `claude plugin validate .` が終了コード 0 で終わり、`python3 scripts/check-skill-frontmatter.py` と `python3 plugins/ndf/scripts/instructions-check.py --root .` が通る -- [ ] 6. `AGENTS.md`・各ランタイムの README・`docs/ndf-plugin-reference.md`・`docs/versioning-and-distribution.md` に「4 ランタイムへほぼ同じ Skill を配る」前提の記述が残らず、codex・agy・kiro が相手役だけを担うことと、配る Skill の一覧の正本(マニフェスト)を指す記述がある -- [ ] 7. ランタイムのスモークテスト(`scripts/runtime-smoke-test.sh` と `.github/workflows/runtime-plugin-smoke*.yml`)が、codex・agy・kiro について配る Skill だけを確かめ、配らない Skill の存在を求めない。CI のスモークのジョブが通る -- [ ] 8. 新しい配布物を導入した環境で、Claude Code をホストに codex・agy・kiro を相手役にした cross-review 1 回と cross-refactoring 1 回が、各相手役の結果ファイルを返して終わる(NO_RESULT が出ない) -- [ ] 9. 配布を絞ると直す必要が無くなる open の課題の一覧(番号と理由)が、実装の PR か本課題に残り、棚卸しで閉じるか残すかが決まる -- [ ] 10. 退行しない: Claude Code 向けのマニフェスト(`claude-skills.txt`)と Claude Code の配布物は変わらず、既存の pytest(`uv run --frozen --project . --all-extras pytest . -q -n 4`)が通る - -## 非機能の条件 - -| 大項目 | 条件 | -| --- | --- | -| 運用・保守性 | codex・agy・kiro へ配る Skill の数が、変更前(codex 45・agy 45・kiro 46)から減り、減った数を実装の PR に実測で書く(Value 3)。ランタイムのスモークテストの所要(秒)を変更の前後で実装の PR に書く | -| 移行性 | 既に codex・agy・kiro へ NDF を入れた利用者が新しい版へ更新したとき、配布から外れた Skill が手元でどうなるか(消える / 残る)をランタイムごとに確かめ、残る場合の消し方を README に書く。こちらから利用者の手元を消さない(C6) | -| システム環境 | 対象のランタイムは今と同じ(Claude Code・Codex・Kiro CLI・agy)。相手役の起動に使う CLI の版の下限は変えない | - -## 影響 - -| 対象 | 影響 | -| --- | --- | -| 公開インタフェース | 変わる。codex・agy・kiro で `$ndf:` などとして呼べた Skill の大半が配布から外れる。互換の経路は持たない(`互換なし`)。Claude Code の公開インタフェースは変わらない | -| データ | 変わらない | -| 既存の振る舞い | codex・agy・kiro をホストにした NDF の工程(`--host codex` など)は保証の外になる(前提 2)。Claude Code をホストにした cross-review / cross-refactoring の振る舞いは変わらない | - -## 検証手段 - -| 項目 | 手段 | -| --- | --- | -| 起動 | `claude plugin validate .`(終了コード 0)。`bash plugins/ndf/dev.kiro/install.sh` を一時ディレクトリで実行し、生成物を見る | -| テスト | `uv run --frozen --project . --all-extras pytest . -q -n 4` | -| 静的解析・型検査 | `python3 scripts/check-skill-frontmatter.py`・`python3 plugins/ndf/scripts/instructions-check.py --root .`・CI の `lint` / `runtime-plugin-validate` / `runtime-plugin-smoke` | -| 手動確認 | リリース後テストで、新しい版を入れた環境から `/ndf:cross-review ` と `/ndf:cross-refactoring ` を 1 回ずつ回し、codex・agy(`--include agy`)・kiro の結果ファイルが揃うことを見る(受け入れ条件 8) | - -## 前提とする取り決め - -| 項目 | 参照先 / 決めたこと | -| --- | --- | -| プロジェクト構造 | 配る Skill の正本は `plugins/ndf/manifests/`(`CLAUDE.md` の「NDF の Skill 構成」)。Skill の実体は `plugins/ndf/skills/` の 1 か所のまま | -| コーディング規約 | `AGENTS.md` の「最小限のコード実装」。`.md` の文言を照合するテストは書かない(`AGENTS.md` の DON'T) | -| テスト戦略 | マニフェストと一覧の突き合わせ・worktreeへ写す Skill の有無は単体のテストで、導入できることはスモークテストで、相手役として動くことはリリース後テストで確かめる | - -## 境界 - -| 区分 | 内容 | -| --- | --- | -| 常に行う | 既存テスト・検査の実行、外したファイルを参照する箇所の掃除 | -| 確認してから行う(承認ゲート 1・2 で人が見る) | 配る Skill の一覧(未決 1)、ホストの役割を残すか(未決 2)、`AGENTS.md` の運用の節の書き換え(C7)、公開インタフェースの縮小 | -| 行わない | Claude Code の配布物の変更、cross 系の振る舞いの変更、open の課題を実装の PR で閉じること、利用者の手元の Skill を消すこと | - -## 未決 - -| 項目 | 誰が決めるか | 期限 | -| --- | --- | --- | -| 1. 相手役に要る Skill の一覧(前提 3 のとおりなら、相手役のランタイムへ配る Skill は 0 件にもなりうる。その場合にマニフェストを空にするか、cross-review・cross-refactoring だけを残すか) | 設計で案を作り、利用者が承認ゲート 1 で決める | 承認ゲート 1 | -| 2. codex・agy・kiro をホストにする使い方を残すか(残すなら `cross-review`・`cross-refactoring`・`fix`・`pr-review` と cross-refactoring の `REQUIRED_SKILLS` が要る) | 利用者(承認ゲート 1) | 承認ゲート 1 | -| 3. 配布から外れた Skill が利用者の手元に残るか(ランタイムごと) | 設計で実測して決める | 設計 PR | -| 4. プロジェクト MVV の Mission(「Claude Code / Codex / Kiro / agy のどれを使うチームにも、要求から本番の配布までの開発工程を…届け」)と Vision が、この変更の後の配布(codex・agy・kiro は相手役だけ)と食い違う。利用者の決定(2026-10-31)は MVV より上位なので要求は進めるが、MVV の改訂(`development-workflow` の `references/project-mvv.md` の「改訂」)を起こすか | 利用者(承認ゲート 1。改訂は利用者の承認で成立する) | 承認ゲート 1 |