Skip to content

Factory の開発ループ: 予算の欄を空にしたら NDF の既定値へ戻す #2406

Closed

Description

@takemi-ohama

依頼(原文)

何をするか

Factory の開発ループで、画面の予算の欄を空にしても NDF の既定値(.ndf/pace.json の loop.budget)へ戻らない。空欄の扱いを決めて直す。

経緯

  • スプリント lfactory2-3 の検査で、クロスレビューが上限に達して後へ回した指摘(スプリント lfactory2-3 #2397 、factory/api/src/runs/control.ts:402、major)
  • NDF に予算を既定値へ戻す引数が無く、Factory は各リポジトリの既定値を知らない

決めること

  • NDF の CLI に既定値へ戻す引数を足すか、画面で空欄を許さないか

受け入れ条件

  • 予算の欄を空にした後の周回で、NDF がリポジトリの既定の予算で止まる条件を判定する。または画面が空欄を断り、理由を出す

(書き手: 起票者、日付: 2026-11-02。スプリント lfactory2-3 の検査で後へ回した指摘を、AI が起票の記録として書いた本文である。利用者の指示の原文は含まない)

指摘の原文( #2397 の修正のまとめ round 1。書き手: AI のレビュー担当):

予算の宣言をnullへ戻す更新も、NDFの既定値へ戻す操作として伝えてください。たとえばusd=10で始めた後に費用欄を空にしても、このフィルターで変更が消え、次の周回は(以下、記録で切れている)

起票者の推定

依頼の全文が起票者の文であるため、題と本文の条件をすべてここに並べる。S4〜S6 は要求の工程で足した条件である。承認ゲート 1 で利用者が確かめるまで、利用者の決定として扱わない。

# 条件 推した出所 この要求での扱い
S1 予算の欄を空にしたら、NDF の既定値(.ndf/pace.json の loop.budget)へ戻す 題と「何をするか」。PR 2397 のクロスレビューの指摘 受け入れ条件 1〜5
S2 直し方は「NDF の CLI に既定値へ戻す引数を足す」か「画面で空欄を許さない」かの 2 つから選ぶ 「決めること」 前者を採る(理由は次の行)。後者は、既定へ戻す手段を持たない NDF の版で動くループに限って使う(受け入れ条件 7)
S3 前者を採る理由: 空欄を断ると、利用者は一度入れた予算をリポジトリの既定へ戻せなくなり、既定の値を自分で調べて書き写すことになる。既定の値の正本は各リポジトリの .ndf/pace.json に残したい 要求の工程の判断(プロジェクト Value 6「プロジェクトごとに違うものは設定で受ける」、スプリント Value 1「操作の手数を減らす」)。Factory の確定仕様は既に「予算が無ければ NDF の既定」を契約にしている(docs/specifications/ndf-factory-dev-loops-data-and-contracts.md の LOOP_BUDGET の行) 受け入れ条件 1〜5
S4 予算の単位が空のときの画面の表示を「掛けない」から、リポジトリの既定に従うことが分かる表示へ変える 要求の工程で足した。空の単位は NDF の既定で止まるため、今の「掛けない」は利用者に「上限が無い」と読ませる(factory/web/src/i18n/ja.json の loops.noBudget) 受け入れ条件 6
S5 既定へ戻す手段を持たない NDF の版で動くループでは、値のあった単位を空にする変更を断り、理由を出す 要求の工程で足した。Factory の実行は版を固定して NDF を導入するため、古い版は新しい手段を解釈できない 受け入れ条件 7
S6 周回のジョブだけでなく、再開のジョブ(#2405 で予算を届ける経路)でも既定へ戻す 要求の工程で足した。#2405 の要求は「単位を外して既定へ戻すこと」を含まないとし、この課題へ渡している 受け入れ条件 4

目的

  • Factory の利用者が開発ループの予算の欄を空にして保存したとき、次の周回から NDF がそのリポジトリの既定の予算で止まる条件を判定する状態にする
  • 画面に出る予算と、NDF が止まる条件の判定に使う予算を食い違わせない

前提

  • 前提 1: 今の食い違いの仕組みは次のとおりである。サービスは実行ジョブの指示に、値のある単位だけを LOOP_BUDGET として並べる(factory/api/src/runs/control.ts の buildInstruction)。NDF の予算の上書き(plugins/ndf/scripts/lib/sprint_loop.py の apply_budget)は渡された単位だけを上書きする。そのため、一度 usd=10 を渡したループの費用の欄を空にしても、ループの記録の費用の予算は 10 のまま残る
  • 前提 2: リポジトリの既定の予算は、既定へ戻す時点のメインディレクトリの .ndf/pace.json の loop.budget の値である。宣言が無い単位は NDF の組み込みの既定(周回 3・費用 60 USD・時間 24 時間。plugins/ndf/scripts/lib/pace.py の LOOP_DEFAULTS)である。ループを始めた時点の値を覚えておくのではない
  • 前提 3: 予算の変更の API(factory/api/src/runs/loops.ts の updateBudget)は、3 つの単位をまとめて置き換える。送らない単位と null の単位は「空」として扱う。この契約は変えない
  • 前提 4: Factory の開発ループ: 再開したジョブへ変えた予算を届ける #2405(再開のジョブへ変えた予算を届ける)の実装が、この課題の実装より先にマージされる。Factory の開発ループ: 再開したジョブへ変えた予算を届ける #2405 は、NDF に予算だけを反映する副命令(sprint-state.py loop budget)を足し、再開のジョブにも LOOP_BUDGET を載せる(issues/issue-2405-design.md)。Factory の開発ループ: 再開したジョブへ変えた予算を届ける #2405 が先にマージされないときは、受け入れ条件 4 を再開のジョブの経路ができた時点へ持ち越す
  • 前提 5: Factory は NDF の版ごとの対応を版の比較で判定する前例を持つ(factory/api/src/runs/version.ts の isLegacyVersion と、並行の実行を許す最小の版の設定)。受け入れ条件 7 の判定も同じ考え方で作れる
  • 前提 6: 既定へ戻す指示を、記録が既に既定の値である単位へ出しても、予算の履歴に行は足さない。サービスは前の値を覚えずに、空の単位を毎回「既定へ戻す」として渡してよい

対象範囲

含む:

  • NDF の開発ループの予算の上書きに、単位ごとに「リポジトリの既定へ戻す」指示を足すこと(loop start と、Factory の開発ループ: 再開したジョブへ変えた予算を届ける #2405 の loop budget の両方)
  • サービスが実行ジョブの指示に空の単位を「既定へ戻す」として載せ、ランナーが NDF へ渡すこと(周回のジョブと再開のジョブ)
  • 実行ジョブの指示の契約(factory/contracts/schemas/run-job-instruction.schema.json の LOOP_BUDGET)の変更
  • 予算の単位が空のときの画面の表示(一覧と詳細の「予算の残り」、予算の欄)
  • 既定へ戻す手段を持たない NDF の版で動くループで、空にする変更を断ること
  • 確定仕様(docs/specifications/ndf-factory-dev-loops*.md・docs/specifications/ndf-factory-contracts-and-progress.md・docs/specifications/ndf-workflow-development-loop.md)と NDF の手順(plugins/ndf/skills/development-workflow/references/loop.md)の予算の記述

含まない:

  • Factory が各リポジトリの既定の予算の値を読んで画面に出すこと。既定の値の正本は各リポジトリの .ndf/pace.json に置いたままにする
  • 再開のジョブへ予算を届ける経路そのもの(Factory の開発ループ: 再開したジョブへ変えた予算を届ける #2405 が持つ)
  • 動いているジョブ(running)の途中で予算を届けること
  • 止まった(stopped)・取り消した(cancelled)ループの予算の変更
  • 予算を「掛けない」(上限を外す)状態を新しく作ること。NDF のループの予算は 3 単位とも常に正の数を持つ

ドメインイベント

# イベント 引き金 失敗したとき 順序の前提
E1 利用者がループの予算の単位を空にして保存した 画面か API の予算の変更 終わりの状態のループは既存のとおり断る。既定へ戻す手段を持たない版のループで、値のあった単位を空にする変更は断り、理由を返す(受け入れ条件 7) ループが running・between_laps・awaiting_approval のいずれか
E2 サービスが次のジョブの指示に、空の単位を「既定へ戻す」として載せた 次の周回のジョブか再開のジョブを作る 既存の断りの理由でジョブを作らない E1 の後に作られたジョブに、E1 の予算が載る
E3 ランナーが NDF へ「既定へ戻す」指示を渡した 周回のジョブでは conductor の起動の指示、再開のジョブでは予算の反映(#2405) 再開のジョブの扱いは #2405 の決定に従う。周回のジョブでは NDF が引数を断り、ループを始めない E2
E4 NDF がループの記録の予算の単位を、リポジトリの既定の値へ戻した E3 .ndf/pace.json を読めないときは既存のとおりループを始めない・反映しない E3 の時点の .ndf/pace.json を読む(前提 2)
E5 NDF が周回を締め、既定の値で止まる条件を判定した conductor が周回を締めるコマンドを打つ 既存のとおり E4

用語

用語 意味
ループの予算 開発ループが使ってよい周回の数・費用(USD)・時間の上限。Factory のループの行と NDF のループの記録の両方が持つ
予算の既定 ループの予算の単位ごとの既定の値。リポジトリの .ndf/pace.json の loop.budget の値で、宣言が無い単位は NDF の組み込みの値
予算の反映 開発ループの記録の予算を、渡した単位の値で上書きすること
予算の履歴 開発ループの記録が持つ、予算の上書きの記録
再開のジョブ START=resume の実行ジョブ。承認の答えで起こすものと、利用上限のリセット時刻の後に起こすものがある
ループの記録 NDF が開発ループごとに持つ .ndf/loop/<名>/loop.json

受け入れ条件

  • 1. 費用の予算 10 USD で始めたループの費用の欄を空にして保存すると、次の周回のジョブの後、NDF のループの記録の費用の予算がリポジトリの .ndf/pace.json の loop.budget.usd の値になる(サービス・ランナー・NDF のテストで、指示・NDF へ渡す引数・記録の予算をそれぞれ確かめる)
  • 2. 受け入れ条件 1 のループで、締めた周回の費用の和が 15 USD(古い予算 10 以上、既定の予算未満)のとき、NDF は budget_usd の止まる条件を記録しない(NDF のテストで確かめる)
  • 3. .ndf/pace.json に loop.budget の宣言が無い単位を既定へ戻すと、NDF の組み込みの既定(周回 3・費用 60・時間 24)になる
  • 4. 承認待ちのループの予算の単位を空にした後、承認の答えで作られた再開のジョブでも、受け入れ条件 1 と同じくループの記録の予算が既定の値になる(前提 4)
  • 5. 既定へ戻す指示で予算が変わったときは予算の履歴に 1 行だけ足し、変わらないとき(既に既定の値のとき・新しいループを始めるとき)は足さない
  • 6. 予算の単位が空のループでは、一覧と詳細の予算の残りに、その単位がリポジトリの既定に従うことが分かる文言を出す。「掛けない」(上限が無い)とは出さない。文言は翻訳のファイルに置く
  • 7. 既定へ戻す手段を持たない NDF の版で動くループで、値のあった単位を空にする変更は、画面と API の両方で断る。理由(その版では既定へ戻せないこと)を返し、画面はその理由を出す。値を入れる変更と、もともと空の単位を空のままにする変更は断らない
  • 8. 3 つの単位すべてに値のあるループの周回と再開は、指示・NDF へ渡す引数・ループの記録の予算がこれまでと変わらない
  • 9. 予算の欄をすべて空にして始めたループは、これまでどおり NDF の既定の予算で動く
  • 10. 「既定へ戻す」を表す値が数でも既定へ戻す指示でもないとき、NDF はループの記録を変えずに引数の誤りとして断る

非機能の条件

大項目 条件
運用・保守性 既定の値を決める規則(.ndf/pace.json の読み方と組み込みの既定)は NDF の 1 か所に置き、Factory に写さない
移行性 既に動いているループと保存済みのループの行は、データの移行なしで次のジョブから新しい規則に乗る。Factory のループの行の予算の形(単位ごとに数か null)は変えない

影響

対象 影響
公開インタフェース 変わる(互換あり)。NDF の sprint-state.py loop start(と #2405 の loop budget)の --budget-* が「既定へ戻す」指示を受けるようになる。数を渡す既存の使い方は変わらない。実行ジョブの指示の契約の LOOP_BUDGET の形が広がる。予算の変更の API は、版によって空にする変更を断る理由が 1 つ増える
データ スキーマの変更は無い。ループの記録の予算の履歴に、既定へ戻した変更が 1 行ずつ足される
既存の振る舞い 空の単位のある周回・再開のジョブで、NDF の予算がその単位の既定へ戻る。画面の空の単位の表示が変わる

検証手段

項目 手段
テスト(Factory) factory/ の既存のテストのコマンド(サービスは factory/api、ランナーは factory/runner、画面は factory/web、契約は factory/contracts)
テスト(NDF) uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests -q -n 4
静的解析・型検査 factory/ の既存の型検査とリンタ。python3 scripts/check-service-boundary.py
手動確認 リリース後テストで、Factory のループの費用の予算を入れて 1 周回した後に欄を空にし、次の周回の後のループの記録の予算と予算の履歴を見る

前提とする取り決め

項目 参照先 / 決めたこと
プロジェクト構造 AGENTS.md の「マーケットプレイスの構造」。plugins/ と .claude-plugin/marketplace.json から factory/ を参照しない(scripts/check-service-boundary.py)。Factory はループの記録を直接書かず、ランナーが NDF の副命令を打って変える(#2405 の設計の腐敗防止層)
コーディング規約 AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストを書かない
テスト戦略 既定の値の決め方と予算の履歴は NDF の単体テスト(plugins/ndf/scripts/tests/test_sprint_loop.py)、指示の組み立てと版による断りはサービスの単体テスト、NDF へ渡す引数の並べ方はランナーの単体テスト、表示は画面のテストで担保する

境界

区分 内容
常に行う 既存のテストの実行、確定仕様と NDF の手順の予算の記述を実装に合わせる
確認してから行う NDF の --budget-* の受ける値を広げること・実行ジョブの指示の契約を変えること(公開インタフェースの変更。承認ゲート 1 で見る)
行わない Factory へリポジトリの既定の値を写すこと、予算を掛けない状態を新しく作ること、#2405 の経路の作り直し

未決

項目 誰が決めるか 期限
1. 「既定へ戻す」の表し方。候補は --budget-usd default のように値で表す形と、--reset-budget usd のように別の引数で表す形。古い版の NDF がどちらを受けたときにどう失敗するか(#2405 の決定 6 は終了コード 2 を「副命令が無い」と読む)を確かめて選ぶ 設計(承認ゲート 1 で利用者が見る) 設計 PR
2. 受け入れ条件 7 の「既定へ戻す手段を持つ版」の判定の仕方(最小の版を設定で持つか、別の手段か) 設計 設計 PR
3. 受け入れ条件 6 の文言 設計 設計 PR

進行

モード: — / 進め方: auto

  • 要求と受け入れ条件 — 2026-11-05 04:18
  • 作業場所の用意 — 2026-11-05 11:35
  • 設計 — 2026-11-05 04:21
  • 素材の収集と出典の確定
  • ドキュメント再構成
  • ドキュメントレビュー
  • 計画 — 2026-11-05 11:35
  • 実装 — 2026-11-05 11:35
  • 構造改善 — 2026-11-05 12:39
  • 実装レビュー — 2026-11-05 13:40
  • 完了判定 — 2026-11-05 11:51
  • Pull Request — 2026-11-05 12:11
  • 確定仕様化 — 2026-11-05 19:13
  • 後片付け — 2026-11-05 19:35
  • 配布 — 2026-11-05 14:01
  • 体裁レビュー
  • リリース後テスト — 2026-11-05 19:30
  • 振り返り — 2026-11-05 19:30
  • 棚卸し — 2026-11-05 19:36

人の判断待ち(開発ループ lfactory3)

  • 判定: unknown(承認ゲート 1)
  • 理由: 設計の中身は MVV に沿っている。既定の値の正本をリポジトリの .ndf/pace.json の一か所に置き、Factory に値を写さない(決定 2)。経路を増やさずに値 default で受け渡す(決定 1)。古い NDF の版へは default を送らず、理由を付けて断る(決定 4・5)。これらは Value 5・Value 6・Value 7 と上位の原則(人を守る)に合う/画面と API・MCP は同じ断りの code(budget_reset_unsupported)を返す。画面の文言は翻訳のファイルに置く(決定 6)。空の予算の単位は『掛けない』でなく『リポジトリの既定』と出す(決定 7)。これらはスプリント Value 1・スプリント Value 4・スプリント Value 5 に沿う。データの移行も要らない(決定 3)/一方で、配布の前に取れる検査 requirements-check が終了コード 2 で止まっている。issues/issue-2406-requirements.md を読めなかったためで、原因は未確認と書かれている。要求と受け入れ条件の文書が正しく揃っているかを材料から確かめられない。設計の承認を MVV 判定だけで通すには根拠が足りない(Value 1「確かめていないものを済んだと記録しない」、Value 2「承認資料の正しさ」)/必ず人の承認が要る操作は、この変更に含まれない。秘密(C1)・認証と認可(C2)・利用者のデータの移行(C3)・戻せない操作(C4)・他のリポジトリへの公開(C5)・.ndf/ と CLAUDE.md の書き換え(C7)・配布物の取得元と版の規則(P1)のどれにも当たらない。NDF_BUDGET_RESET_MIN_VERSION は Factory の内部の設定で、配布の版の規則(P1)ではない
  • 根拠の項目: Mission, Vision, Value 1, Value 2, Value 5, Value 6, Value 7, スプリント Value 1, スプリント Value 4, スプリント Value 5, C3, C5, C7, P1
  • 設計 Pull Request: Factory の開発ループ: 予算の欄を空にすると、次のジョブからリポジトリの既定の予算で止まる判定を行う(#2406) #2541
  • 答え: approved
  • 答え方: python3 /persistent/ai/.claude/plugins/cache/ai-plugins/ndf/10.27.19/scripts/sprint-state.py loop answer lfactory3 2406 --approved|--rejected|--revise --note <指摘ファイル>

振り返り: #2587 (comment)

Activity

  1. added
    quality品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)
    on Nov 2, 2026
  2. added 2 commits that reference this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    quality品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions