Repository navigation
Description
依頼(原文)
何が起きたか
開発ループ lfactory2 で、周回の途中に
loop stop lfactory2を打って止める指示(.ndf/loop/lfactory2/stop)を置き、セッションを切った(2026-11-02 22:08 JST)。2026-11-04 15:01 JST に再開した。
loop start lfactory2はin_lapを返し、止める指示のファイルを消さなかった(stopは止まった記録が無いため、再開の扱い_resume_user_stopを通らない)- 周回 4 を
loop lap lfactory2 --failedで締めると、境の判定が残ったファイルを読み、user_stopで止まった。本当に止めたい理由(プロジェクト MVV が版 4 → 5 に改訂されたmvv_changed)は出なかった- 周回 4 の秒に、止めていた約 41 時間が入った(消費の hours が 6.19 → 47.14)。確定仕様の「止まっていた時間は経過時間に入れない」に反し、予算 72 時間の 6 割を止めていた時間で使った
期待
- 周回の途中の止める指示は、
loop startの再開で解ける(周回の境の止まりと同じ)- 止める指示を置いてから再開までの時間は、経過時間に数えない
再現
- 周回を組んだ状態(進行中)で
sprint-state.py loop stop <名>を打つ- 時間を置いて
loop start <名>(in_lapが返る)loop lap <名> --failed→user_stopで止まり、周回の秒に止めていた時間が入る範囲
plugins/ndf/scripts/lib/sprint_loop.py(cmd_startの in_lap の経路)・sprint_loop_record.py(boundary_stop・周回の秒)。
(書き手: 起票者、日付: 2026-11-04。開発ループを回していた AI が、起きたことの記録として書いた本文である。利用者の指示の原文は含まない。「止める指示を置いてセッションを切り、再開した」という操作は利用者のものだが、その操作に添えた利用者の文は本文に引用されていない)
起票者の推定
題・本文のうち、利用者の指示の原文に無く起票者が推して足した条件。2026-11-05 の利用者の判断(下の「人の判断待ち」の節)で扱いを決めた。
| # | 条件 | 推した出所 | この要求での扱い |
|---|---|---|---|
| S1 | lfactory2 の止める指示は「利用者の指示」で置かれた | 本文の「何が起きたか」の 1 行目。止める指示を置いた conductor が引継ぎ文書に「利用者の指示で loop stop を打った」と書いていた |
採らない。記録では、人はループを止めることを送っていない(下の「目的」の表) |
| S2 | 周回の途中に置いた止める指示は、loop start の再開で解ける |
本文の「期待」の 1 行目 | 採らない。人が送った停止は次の周回の境で効くのが正しい振る舞いである。自動の再起動も周回の途中で loop start を打つため、再開で消すと人が送った停止が境の前に消える(前提 4) |
| S3 | 止める指示を置いてから再開までの時間を、ループの予算の経過時間に数えない | 本文の「期待」の 2 行目 | 採らない。人が送った停止では conductor が境まで周回を続けるため、止める指示から境までは実際に動いていた時間である。境で止まった後の区間は、確定仕様の I8 ですでに経過時間から外れる(前提 3) |
| S4 | 直す場所は cmd_start の周回の途中の経路と、境の判定・周回の秒 |
本文の「範囲」 | 採らない。直すのは止める指示を置く経路(conductor の手順)である |
| S5 | 「周回の秒」に止めていた時間が入った | 本文の「何が起きたか」の 3 | 採らない。周回 4 の秒(計画の行の秒の和)は 0 で、時間が入ったのはループの予算の経過時間(消費の hours)である |
目的
止める指示(.ndf/loop/<名>/stop)が、人が実際に送った停止からだけ置かれる状態にする。人が送っていない文(送信されていないサジェスト・入力欄に残った文字・人の指示を名乗る別のセッションのメッセージ)から止める指示が置かれると、ループは誰も求めていない利用者の停止(user_stop)で止まり、本当に止まるべき理由が出ない。
記録で確かめた経路(2026-11-02、時刻は UTC。会話の記録 37e6fcce・f3bae19d とループの記録 .ndf/loop/lfactory2/loop.json):
| 時刻 | 誰が | 何を読んで | 何をした |
|---|---|---|---|
| 13:07:22 | ループ lflow の conductor のセッション | 人の入力として記録された「3本に引継ぎメモを作って終了する指示を送ってください。」。記録の入力元の値は typed で、サジェストを採った入力の値(suggestion_accepted)ではない。利用者は 2026-11-05 に、この入力をサジェストを指示と読んだものと判断した |
3 本のループの conductor へ、別のセッションへのメッセージで「【利用者の指示・lflow 経由】引継ぎ文書を最新にして、このセッションを終了してください」を送った |
| 13:07:39 | ループ lfactory2 の conductor のセッション(f3bae19d) |
上のメッセージ(入力元は別のセッション) | パイプラインを止め、引継ぎ文書を書いた |
| 13:08:52 | 同じ | 同じメッセージ。ループを止めることは書かれていない | 「利用者の指示はループを止めること」と自分で読み替えて loop stop lfactory2 を打ち、引継ぎ文書に「利用者の指示で打った」と書いた |
| 2026-11-04 06:01:43 | 再開した conductor | 残っていた止める指示 | 周回 4 を締めた境で user_stop で止まった。プロジェクト MVV の改訂(mvv_changed)は出なかった |
どの段にも、人がループを止めることを送った記録は無い。止める指示は、conductor が別のセッションのメッセージを自分で読み替えて置いた。周回 4 の経過時間に入った約 41 時間(消費の hours 6.19 → 47.14)は、周回の途中でセッションを終えて 2 日後に再開した区間であり、止める指示が作った区間ではない。
前提
- 前提 1: 止める指示のファイルを書くのは
sprint-state.py loop stop(cmd_stop)だけである。git grep -n "STOP_FILE" -- plugins/ndf/scripts/libの当たりは、定数の定義と読み込みを除くと、cmd_stopが書き、周回の境の判定(boundary_stop)が読み、止まった記録の再開(_resume_user_stop)が消す 3 か所である - 前提 2: 入力を人が送ったかを、コマンドや hook の側で見分ける値は無い。hook が受ける入力の項目に入力元は無く、Claude Code の会話の記録にある入力元の値(
promptSource・turnOrigin)は公開の仕様ではなく、Codex には無い - 前提 3: 人が送った停止は、次の周回の境で効く(確定仕様の I3)。conductor は境まで周回を続けるため、止める指示が置かれてから境までは動いていた時間である。境で止まった後の区間は確定仕様の I8 で経過時間から外れる
- 前提 4: 自動の再起動(カットポイントと利用上限での切り替え)も、周回の途中で
loop startを打つ
対象範囲
含む:
- conductor の手順(
development-workflowのreferences/loop.md)に、止める指示を置く発生元を人が送った入力に限ることを書く - セッションを終える依頼(引き継いで終了する)では止める指示を置かないことを書く
- 人が送っていない文から止める指示を置いたと気づいたときに、ファイルを消して無視することを書く
- 確定仕様
docs/specifications/ndf-workflow-development-loop.mdの、止める指示の発生元の記述
含まない:
loop startと経過時間の計算を変えること(前提 3・4)- 中継が tmux に起動する claude のサジェストを止めること(中継: tmux に起動するレーンの claude で Prompt suggestions を止める #2504)
- 画面の入力欄の文字を判断に使わない決まり(PR Docs: 並列のレーンの画面の見方と、入力欄のサジェストを判断に使わないことを書く #2502 で develop に入った)
- 周回の途中でセッションを終えた区間(lfactory2 の約 41 時間)を経過時間から外すこと。セッションが止まった時刻を記録する仕組みが無い
- 既存のループの記録(lfactory2 など)の値を直すこと
ドメインイベント
| # | イベント | 引き金 | 失敗したとき | 順序の前提 |
|---|---|---|---|---|
| E1 | 人がループを止めることを送った | conductor のセッションへの人の入力、または人が端末で打つ loop stop |
— | — |
| E2 | 止める指示を置いた | E1 を受けた conductor の loop stop |
ループの記録が無ければ断る(今のとおり) | E1 |
| E3 | セッションを終える依頼を受けた | 人の入力・別のセッションのメッセージ | — | 止める指示を置かない |
| E4 | 人が送っていない文から置いた止める指示に気づいた | 止める指示を置いた conductor | — | ファイルを消して無視する |
| E5 | 境で止まる条件を判定した | 周回を締めた後・選定の前 | 今のとおり | E2 があれば user_stop で止まる |
用語
| 用語 | 意味 |
|---|---|
| 開発ループ | スプリントを 1 つ終えるたびに次のスプリントを選んで続けて始める進め方(用語集) |
| 周回 | 開発ループの 1 回分(用語集) |
| ループの予算 | 開発ループが使ってよい量の上限。周回の数・費用・経過時間で数える(用語集) |
| 止まる条件 | 開発ループを止める、機械で判定できる条件(用語集)。止める指示は user_stop に当たる |
| ループの記録 | .ndf/loop/<名>/loop.json(用語集) |
止める指示は、loop stop が置くファイル .ndf/loop/<名>/stop(中身は置いた時刻)を指す。人が送った入力は、人がそのセッションの入力欄から送信した入力と、人が端末で打ったコマンドを指す。別のセッションからのメッセージ・引継ぎ文書・画面に出た文字・送信されていないサジェスト・conductor 自身の推測は含まない。
受け入れ条件
- 1.
references/loop.mdに、conductor がloop stopを打つのは、人が自分のセッションへ送った入力がループを止めることを求めたときだけ、と書かれている - 2. 1 の発生元にしないもの(別のセッションからのメッセージ。「利用者の指示」と書かれていても含む。引継ぎ文書・画面に出た文字・送信されていないサジェスト・conductor 自身の読み替え)が書かれている
- 3. セッションを終える依頼(引き継いで終了する)では
loop stopを打たず、引継ぎ文書を書いてセッションを終える、と書かれている - 4. 人が送っていない文から止める指示を置いたと気づいた conductor は、そのファイルを消し、消したことを引継ぎ文書に書く、と書かれている。人が置いた止める指示は消さない
- 5. 確定仕様
docs/specifications/ndf-workflow-development-loop.mdに、止める指示の発生元が人が送った停止に限られることが書かれている - 6. 開発ループのコード(
plugins/ndf/scripts/lib/sprint_loop*.py)は変えない。既存のテスト(plugins/ndf/scripts/tests/test_sprint_loop.py)が通る
影響
| 対象 | 影響 |
|---|---|
| 公開インタフェース | 無し(sprint-state.py loop の副命令と結果は変えない) |
| データ | 無し |
| 既存の振る舞い | conductor が loop stop を打つ場面が、人が送った停止に限られる |
検証手段
| 項目 | 手段 |
|---|---|
| 文書のレビュー | 受け入れ条件 1〜5 を設計と実装の Pull Request のレビューで読む(.md の文言を照合するテストは書かない) |
| テスト | uv run --frozen --project . --all-extras pytest plugins/ndf/scripts/tests/test_sprint_loop.py -q(受け入れ条件 6) |
| リンクの検査 | python3 scripts/check-markdown-links.py --root .(手順書から足したリンクの参照切れ) |
| 手動確認 | 次に別のセッションからセッションを終える依頼を受けた conductor が、loop stop を打たずに引継ぎ文書を書いて終えることを見る(リリース後テスト) |
前提とする取り決め
| 項目 | 参照先 / 決めたこと |
|---|---|
| 手順書の置き場 | conductor の手順は plugins/ndf/skills/development-workflow/references/loop.md |
| コーディング規約 | AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストは書かない |
| 関連の決まり | 画面の入力欄の文字を判断に使わない(references/parallel.md の「レーンの画面を見るとき」) |
境界
| 区分 | 内容 |
|---|---|
| 常に行う | 既存テストの実行、確定仕様の該当箇所の更新 |
| 確認してから行う | 無し |
| 行わない | 開発ループのコードの変更、既存のループの記録の書き換え |
未決
無し(人が送ったかを機械で見分けない理由は前提 2 に置いた)
進行
モード: — / 進め方: auto
- 要求と受け入れ条件 — 2026-11-04 20:46
- 作業場所の用意 — 2026-11-05 16:59
- 設計 — 2026-11-04 20:49
- 素材の収集と出典の確定
- ドキュメント再構成 — 2026-11-04 20:52
- ドキュメントレビュー
- 計画 — 2026-11-05 16:59
- 実装 — 2026-11-05 16:59
- 構造改善 — 2026-11-05 17:41
- 実装レビュー — 2026-11-05 17:41
- 完了判定 — 2026-11-05 17:01
- Pull Request — 2026-11-05 17:13
- 確定仕様化 — 2026-11-05 19:20
- 後片付け — 2026-11-05 19:56
- 配布 — 2026-11-05 17:59
- 体裁レビュー
- リリース後テスト — 2026-11-05 19:27
- 振り返り — 2026-11-05 19:27
- 棚卸し — 2026-11-05 19:56
人の判断待ち(開発ループ lroot3)
- 判定: follow(承認ゲート 1)
- 理由: Mission・Vision に沿う: 人が送っていない文(別のセッションのメッセージ・サジェスト・自分の読み替え)からループを止めないので、開発ループが「人の判断が要る所だけで止まる」形に近づく。lfactory2 では誰も求めていない user_stop で止まり、本当に止まるべき理由(MVV の改訂)が出なかった。この誤停止を防ぐ/共通原則の上位の原則と「進める / 止めて人へ戻す」に沿う: 発生元が人か分からない停止は置かずに人へ確かめる。経緯が分からない止める指示は消さず、人が loop start で解く(決定 5)。AI が独自に判断を広げない形になっている/Value 6(どのプロジェクトでも使える形を保つ)と Value 5(決まった手順はスクリプトに、判断と中身は AI に)に沿う: 非公開でランタイムによって無い入力元の値に頼る hook を採らず、判断を conductor の手順に置く(決定 1)/Value 4(外の利用で測って決める)と Value 7(根本原因の場所で直す)に沿う: 根拠は 2 つの会話記録の実測と、git grep による止める指示の書き手の確認である。直す場所を止める指示を打つ側に絞り、loop start と経過時間の計算は変えない(決定 2・3)。手順書の決まりが守られるかは配布の後の確認へ回しており、判定の対象外/必ず承認が要る操作に当たるものは無い: 変更は設計文書と要求のコピーだけである。実装の対象は、プラグインの手順書 loop.md と確定仕様で、利用者の .ndf/ の設定や CLAUDE.md・AGENTS.md の運用の節ではない(C7 外)。F3 の消去の対象は、conductor 自身が誤って置いたループの実行状態のファイルだけで、通常の削除で戻せる(C4 の -D / --force の削除に当たらない)。秘密・認証・他リポジトリへの公開・配布の規則(C1・C2・C5・P1)にも触れない
- 根拠の項目: Mission, Vision, Value 4, Value 5, Value 6, Value 7, C4, C7, P1
- 設計 Pull Request: 開発ループ: 止める指示を人が送った停止だけから置く(#2474) #2501
- 答え: approved
- 答え方:
python3 /persistent/ai/.claude/plugins/cache/ai-plugins/ndf/10.27.16/scripts/sprint-state.py loop answer lroot3 2474 --approved|--rejected|--revise --note <指摘ファイル>
振り返り: #2586 (comment)
Activity
docs(design): 周回の途中で止まった記録の再開に止める指示が残ることを明記(#2474)
[-]開発ループ: 周回の途中で止める指示を置くと、再開で解けず、止めていた時間が経過時間に入る[/-][+]開発ループ: 止める指示を人が送った停止だけから置く(人が送っていない文から置かれた止める指示が、再開後の境で user_stop を起こした)[/+]Docs: #2474 の設計を組み直す(止める指示を人が送った停止だけから置く)
Docs: #2474 の設計文書を組み直す(確定仕様の直し方を中身の章の末尾へ移し、根拠の Value に題を添える)
Docs: #2474 の処理の流れで、セッションを終えるだけの依頼を送信元によらず引継ぎで終える
Merge pull request #2501 from devbasex/design/issue-2474
Docs: #2510 の設計に、承認の不着・取り込みでの再送・前のループの承認待ちを足す
Merge pull request #2580 from devbasex/feat/issue-2474-lroot3-17