Repository navigation
Open
Labels
quality品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)
Milestone
Description
依頼(原文)
何をするか
Factory の開発ループで、承認待ち・利用上限待ちの間に画面で予算を変えても、再開したジョブ(START=resume)は古い予算のまま進む。再開したジョブへ変えた予算を届ける。
経緯
- スプリント lfactory2-3 の検査で、クロスレビューが上限(4 ラウンド)に達して後へ回した指摘(スプリント lfactory2-3 #2397 、
factory/api/src/runs/control.ts:400、major)- 今の NDF には再開したループへ予算を渡す口が無く、上書きできるのはループを始めるときの
--budget-*だけ(NDF Factory: 開発ループ・並行する実行の調整・ジョブの中の区切りと利用上限・手元のランナーの同時実行数・ループの見え方を定義する #2347 の設計の決定 14)決めること
- ランナーが再開の前に NDF の
loop start --budget-*を打ち直すか、再開の指示へ予算を足すか受け入れ条件
- 承認待ちの間に予算を変えたループを再開すると、NDF の止まる条件の判定が新しい予算で行われる(テストで確かめる)
(書き手: 起票者、日付: 2026-11-02。スプリント lfactory2-3 の検査で後へ回した指摘を、AI が起票の記録として書いた本文である。利用者の指示の原文は含まない)
起票者の推定
依頼の全文が起票者の文であるため、題と本文の条件をすべてここに並べる。承認ゲート 1 で利用者が確かめるまで、利用者の決定として扱わない。
| # | 条件 | 推した出所 | この要求での扱い |
|---|---|---|---|
| S1 | 再開したジョブ(START=resume)へ、画面で変えた予算を届ける |
PR 2397 のクロスレビューの指摘( #2397 )。factory/api/src/runs/control.ts の実行ジョブの指示の組み立てが、予算を START=loop のときだけ載せている |
受け入れ条件 1・2 |
| S2 | 対象の場面は「承認待ち」と「利用上限待ち」の間の変更 | 起票者の判断。再開のジョブを作る経路が、承認の答えによる再開とリセット時刻の後の再開の 2 つであること | 受け入れ条件 1・2。周回の間の変更は既に届くため含まない(前提 1) |
| S3 | 今の NDF には再開したループへ予算を渡す口が無く、上書きできるのはループを始めるときの --budget-* だけ |
#2347 の設計の決定 14 | 前提 2 で事実を補う(既にあるループへの loop start --budget-* も予算を上書きするが、ほかの処理を伴う) |
| S4 | 届け方は「ランナーが再開の前に loop start --budget-* を打ち直す」か「再開の指示へ予算を足す」かの 2 つから選ぶ |
起票者の判断 | 未決 1(設計で決める。選択肢を 2 つに限らない) |
| S5 | 新しい予算で止まる条件の判定が行われることを、テストで確かめる | 起票者の判断 | 受け入れ条件 3・4 |
目的
- Factory の利用者が、承認待ちや利用上限待ちで止まっている開発ループの予算を画面で変えたとき、ループが再開した後に NDF がその予算で止まるかを判定する状態にする
- 画面に出る「予算の残り」と、NDF が止まる判定に使う予算を食い違わせない
前提
- 前提 1: 周回の間(
between_laps)に変えた予算は、次の周回のジョブ(START=loop)の指示のLOOP_BUDGETから--budget-*として NDF へ渡っており、この課題では変えない。根拠:factory/runner/src/runtime.tsのloopPromptがLOOP_BUDGETを--budget-<単位> <値>へ並べ、factory/runner/src/loop.test.tsの「--budget-laps 3 --budget-usd 60」の例がそれを確かめている - 前提 2: NDF のループの記録(
.ndf/loop/<名>/loop.json)は既にあるループにもloop start <名> --budget-*で予算を上書きでき、変わったときだけ予算の履歴(budget_history)に 1 行足す(plugins/ndf/scripts/lib/sprint_loop.pyのapply_budget)。ただし既にあるループへのloop startは、止まった記録を解く手続き(承認ゲート 2 の答えの処理・周回の締め・予算超過の判定し直し)も同時に行う(同じファイルのcmd_start・resume_stopped) - 前提 3: NDF の止まる条件の判定は、周回を締めるときにループの記録の予算と締めた周回の消費の和を比べる(
plugins/ndf/scripts/lib/sprint_loop_record.pyの予算の判定)。したがって conductor を起こす前にループの記録の予算が新しい値になっていれば、その後の判定は新しい予算で行われる - 前提 4: 実行ジョブの指示の契約(
factory/contracts/schemas/run-job-instruction.schema.json)は、ループの実行のresumeにLOOP_BUDGETを載せることを既に許している。契約の形は変えない - 前提 5: 予算をループの記録へ反映できなかったときは、conductor を起こさずにジョブを失敗で終える。古い予算のまま進めると、この課題が直す食い違いをそのまま残すためである。人の判断待ちへの答えを書けなかったとき(
factory/runner/src/runtime.tsのanswerLoop)と同じ扱いにする
対象範囲
含む:
- 承認の答えによる再開(
APPROVAL_REQUEST_IDのあるSTART=resume)で、Factory のループの今の予算を NDF のループの記録へ反映すること - 利用上限の後の再開(
APPROVAL_REQUEST_IDの無いSTART=resume)で、同じく反映すること - 反映を確かめる自動テスト(Factory のサービスとランナー、必要なら NDF のスクリプト)
- 確定仕様(
docs/specifications/ndf-factory-dev-loops.mdほか)の予算の変更の記述を、再開のジョブにも届くことに合わせる
含まない:
- 動いているジョブ(
running)の途中で予算を届けること。変えた予算は次に作るジョブ(再開か次の周回)で届く - 画面で予算の単位を空にした(制限を外した)ときに、NDF の予算を既定へ戻すこと。今の NDF の
--budget-*は値の上書きだけを持ち、外す口が無い。周回のジョブでも同じ制約があり、別の課題で扱う - 止まった(
stopped)・取り消した(cancelled)ループの再開。決定 14 のとおり終わりの状態であり、続きは新しいループで始める - 予算の変更の画面と API(
updateBudget)の形の変更
ドメインイベント
| # | イベント | 引き金 | 失敗したとき | 順序の前提 |
|---|---|---|---|---|
| E1 | 利用者がループの予算を変えた | 画面か API の予算の変更(updateBudget) |
終わりの状態のループは already_finished で断る(既存) |
ループが running・between_laps・awaiting_approval のいずれか |
| E2 | サービスが再開のジョブを作った | 承認の答え(requestResume)か、リセット時刻の経過(resumeAfterReset) |
既存の断りの理由(sprint_run_busy など)で作らない |
E1 の後に作られたジョブに、E1 の予算が載る |
| E3 | ランナーが保存した状態を復元した | 再開のジョブの起動 | 既存のとおりジョブを失敗にする | E2 |
| E4 | ランナーがループの記録の予算を新しい値にした | E3 の完了 | conductor を起こさずジョブを失敗で終える(前提 5) | E3 の後、conductor の起動の前 |
| E5 | conductor が前回の続きから進めた | E4 の完了(予算を宣言していないループでは E3 の完了) | 既存のとおり | E4 |
| E6 | NDF が周回を締め、止まる条件を新しい予算で判定した | conductor が周回を締めるコマンドを打つ | 既存のとおり | E4 |
E4 と人の判断待ちへの答えの書き込み(既存)の順序は、どちらが先でも結果が同じになることを設計で確かめる(未決 2)。
用語
| 用語 | 意味 |
|---|---|
| ループの予算 | 開発ループが使ってよい周回の数・費用(USD)・時間の上限。Factory のループの行と NDF のループの記録の両方が持つ |
| 再開のジョブ | START=resume の実行ジョブ。承認の答えによるものと、利用上限の後のものがある |
| ループの記録 | NDF が開発ループごとに持つ .ndf/loop/<名>/loop.json。予算・予算の履歴・周回・止まった理由を持つ |
受け入れ条件
- 1. 承認待ち(
awaiting_approval)のループの予算を変えた後に、承認の答えで作られた再開のジョブでは、conductor を起こす前に NDF のループの記録の予算が変えた値になっている(ランナーのテストで、記録の予算を読んで確かめる) - 2. 利用上限待ち(
awaiting_reset)の実行のループの予算を変えた後に、リセット時刻の後に作られた再開のジョブでも、受け入れ条件 1 と同じになる - 3. 予算を下げて再開した場合、締めた周回の消費の和が新しい予算以上になった周回の締めで、NDF が
budget_<単位>の止まる条件を記録する(例: 費用の予算を 60 から 40 へ下げ、消費の和 50 で締めるとbudget_usdで止まる) - 4. 予算を上げて再開した場合、古い予算なら止まっていた消費の和でも NDF は止まる条件を記録しない(例: 費用の予算を 40 から 100 へ上げ、消費の和 50 で締めると止まらない)
- 5. 再開のジョブの指示に載る予算は、そのジョブを作った時点の Factory のループの予算である(サービスのテストで、
requestResumeとresumeAfterResetの両方の指示にLOOP_BUDGETが載ることを確かめる) - 6. 予算が変わっていないときは、予算の履歴に行を足さない。変わったときは 1 行だけ足す
- 7. 予算を反映する操作は、ループの記録の予算と予算の履歴のほかを変えない。止まった記録の解除・周回の締め・承認ゲート 2 の答えの処理は、conductor が前回の続きから進めるときに既存のとおり 1 回だけ起きる
- 8. 予算をどの単位も宣言していないループの再開では、ループの記録の予算を変えない
- 9. ループに属さない実行の再開のジョブは、指示も振る舞いも変わらない(
LOOP_BUDGETを載せない) - 10. ループの記録へ予算を反映できなかったとき、ランナーは conductor を起こさずにジョブを失敗で終え、理由をジョブの出力に残す
非機能の条件
| 大項目 | 条件 |
|---|---|
| 運用・保守性 | 予算の上書きの規則(単位ごとの上書きと予算の履歴)は NDF の 1 か所に置き、ランナーとサービスに同じ規則を写さない |
| 移行性 | 既に動いているループと保存済みの状態は、そのまま次の再開のジョブで新しい規則に乗る。データの移行は要らない |
影響
| 対象 | 影響 |
|---|---|
| 公開インタフェース | 変わらない。実行ジョブの指示の契約は再開のジョブの LOOP_BUDGET を既に許している(前提 4)。NDF に予算だけを反映するコマンドを足すかは未決 1 |
| データ | スキーマの変更は無い。NDF のループの記録の予算の履歴に、再開のときの変更が 1 行ずつ足される |
| 既存の振る舞い | 再開のジョブで、conductor の起動の前に予算の反映が入る。周回のジョブとループに属さない実行は変わらない |
検証手段
| 項目 | 手段 |
|---|---|
| テスト(Factory) | factory/ の既存のテストのコマンド(サービスは factory/api、ランナーは factory/runner のテスト) |
| テスト(NDF) | uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests -q -n 4(NDF のスクリプトを変えるとき) |
| 静的解析・型検査 | factory/ の既存の型検査とリンタ |
| 手動確認 | リリース後テストで、Factory のループを承認待ちで止めて予算を変え、答えで再開した後のループの記録の予算と予算の履歴を見る |
前提とする取り決め
| 項目 | 参照先 / 決めたこと |
|---|---|
| プロジェクト構造 | AGENTS.md の「マーケットプレイスの構造」。plugins/ と .claude-plugin/marketplace.json から factory/ を参照しない(scripts/check-service-boundary.py)。ランナーは NDF のスクリプトを、導入した版の取得元の写しから呼ぶ(既存の answerLoop と同じ) |
| コーディング規約 | AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストを書かない |
| テスト戦略 | 指示の組み立てはサービスの単体テスト、反映の順序と失敗の扱いはランナーの単体テスト、予算の判定は NDF の既存のテスト(plugins/ndf/scripts/tests/test_sprint_loop.py)で担保する |
境界
| 区分 | 内容 |
|---|---|
| 常に行う | 既存のテストの実行、確定仕様の予算の変更の記述を実装に合わせる |
| 確認してから行う | NDF のスクリプトへ新しい副命令を足すこと(公開インタフェースの追加。承認ゲート 1 で見る) |
| 行わない | 予算の単位を外す口の追加、動いているジョブへの予算の割り込み、止まったループの再開 |
未決
| 項目 | 誰が決めるか | 期限 |
|---|---|---|
1. 予算をループの記録へ反映する手段。候補は (a) ランナーが既存の loop start <名> --budget-* を打つ、(b) 再開の指示の文へ予算を足して conductor に打たせる、(c) NDF に予算だけを反映する副命令を足してランナーが打つ。(a) は止まった記録を解く手続きを conductor より先に起こすため、受け入れ条件 7 を満たせるかを確かめる。(b) は決まった手順を AI に任せる形になる |
設計(承認ゲート 1 で利用者が見る) | 設計 PR |
| 2. 予算の反映と、人の判断待ちへの答えの書き込み(既存)の順序 | 設計 | 設計 PR |
進行
モード: — / 進め方: auto
- 要求と受け入れ条件 — 2026-11-04 08:06
- 作業場所の用意
- 設計 — 2026-11-04 08:09
- 素材の収集と出典の確定
- ドキュメント再構成 — 2026-11-04 08:15
- ドキュメントレビュー
- 計画
- 実装
- 構造改善
- 実装レビュー
- 完了判定
- Pull Request — 2026-11-04 14:37
- 確定仕様化 — 2026-11-04 14:30
- 後片付け — 2026-11-04 15:02
- 配布
- 体裁レビュー
- リリース後テスト — 2026-11-04 14:58
- 振り返り — 2026-11-04 14:58
- 棚卸し — 2026-11-04 15:02
人の判断待ち(開発ループ lfactory3)
- 判定: unknown(承認ゲート 1)
- 理由: 設計の中身は MVV に沿っている。再開のジョブへ変更後の予算を届ける。予算の上書きは既存の apply_budget の 1 か所に寄せる(Value 7)。決まった手順は conductor に任せず、ランナーが終了コードで成否を決める(Value 5)。どれも Mission と Vision の「人の判断が要る所だけで止まる」開発ループの正しさに寄与する/要求の検査(requirements-check)が終了コード 2 で止まった。対象の issues/issue-2405-requirements.md は PR に含まれているのに読めず、原因は確認されていない。要求と受け入れ条件が検査を通るかは材料から決められない。Value 1 は自動テストで守り、確かめていないものを済んだと扱わないことを求める。そのため、検査が止まったまま関門を自動で通すかは人へ戻す/決定 6 は、副命令が無い NDF(終了コード 2)では反映せずに続ける。版を固定した既存の実行の再開を止めない判断で、共通原則の「人を守る」と Value 1 に沿う。ただし argparse は値の誤りでも終了コード 2 を返すため、渡した予算の値の誤りも「副命令が無い」と読まれて素通りしうる。この点は設計の確認事項として残る/秘密・認証・利用者のデータ・戻せない操作・他のリポジトリへの公開・.ndf/ や CLAUDE.md の書き換えには当たらない(C1〜C8)。配布物の取得元と版の規則も変えない(P1)。API と画面の間で操作の差は生まない(スプリント Value 4)/決定 6 の確認コマンドは実行して確かめてある(Value 4)。未確認のまま残ること(実物の通し、古い版の実行の数)は表に明記してある(Value 8)。配布の後に確かめる項目は判定の対象にしない
- 根拠の項目: Mission, Vision, Value 1, Value 4, Value 5, Value 7, Value 8, C1, C3, C4, C5, C7, P1, スプリント Value 4
- 設計 Pull Request: Factory の開発ループ: 承認待ち・利用上限待ちの間に変えた予算で、再開した後の止まる判定を行う(#2405) #2478
- 答え: approved
- 答え方:
python3 /persistent/ai/.claude/plugins/cache/ai-plugins/ndf/10.27.15/scripts/sprint-state.py loop answer lfactory3 2405 --approved|--rejected|--revise --note <指摘ファイル>
振り返り: #2490 (comment)
Metadata
Metadata
Assignees
Labels
quality品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)品質向上の Issue(棚卸しの品質の枠。.ndf/backlog.json の quality)
Activity
Docs: #2405 の設計の不変条件を 1 行 1 条件に分け、予算の履歴と人の判断待ちの行を用語集へ足す
Merge pull request #2478 from devbasex/design/issue-2405