Skip to content

Factory の確定仕様で不変条件の番号 I44〜I50 が重なり、同じ番号が別の条件を指す #2445

Open

Description

@takemi-ohama

依頼(原文)

(書き手: 起票者。#2439 の設計の作業中に AI が起票した本文。日付: 2026-11-03。利用者の指示の引用は含まない。下は起票時の本文をそのまま引用する)

何が困るか

Factory の確定仕様の不変条件の番号(I<数>)は通し番号として振る決まりである(docs/specifications/ndf-factory-contracts-and-progress.md の 339 行目「#2170 の I24 に続けて番号を振る」)。ところが develop(2026-11-03)で、同じ番号が別のファイルの別の条件に使われている。

番号 使っているファイル(develop)
I44 ndf-factory-contracts-and-progress.md ndf-factory-dev-loops.md
I45 ndf-factory-contracts-and-progress.md ndf-factory-dev-loops.md
I46 ndf-factory-dev-loops.md ndf-factory-issue-requests.md
I47 ndf-factory-dev-loops.md ndf-factory-issue-requests.md
I48 ndf-factory-dev-loops.md ndf-factory-issue-requests.md
I49 ndf-factory-dev-loops.md ndf-factory-issue-requests.md
I50 ndf-factory-contracts-and-progress.md ndf-factory-dev-loops.md

ndf-factory-sprint-views.md も I1〜I14 を自分の条件に振っており、ほかのファイルの別の条件と番号が重なる(2026-11-05 の develop 1b32edb)。

番号 重なる相手(develop)
I1〜I7・I11 ndf-factory-service-boundary.md
I8・I9 ndf-factory-runs-and-runner.md・ndf-factory-service-boundary.md
I10 ndf-factory-contracts-and-progress.md・ndf-factory-service-boundary.md
I12〜I14 ndf-factory-accounts-and-plans.md

例: I12 は ndf-factory-sprint-views.md では「4 つの読み出しは、解決したアカウントの実行とリポジトリだけを返す」、ndf-factory-accounts-and-plans.md では「1 人の利用者の個人のアカウントは 1 つだけ」を指す。

I8・I9・I10 も 2 つのファイルに出るが、同じ条件を ndf-factory-service-boundary.md が再掲したもので、重なりではない。

例: I48 は ndf-factory-dev-loops.md では「並行を許す版の下限より古い NDF の版の実行は唯一」、ndf-factory-issue-requests.md では「同じ依頼から作る Issue は 1 件まで」を指す。#2439 の設計(PR #2442 )は I48 を引くたびにどちらかを書き分ける必要があった。

直し方の案

  • 番号の振り方を「ファイルごとの接頭辞(例: DL-I48)」か「真の通し番号」のどちらかに決め、重複を振り直す
  • 構造チェックに、Factory の確定仕様の間で表の 1 列目の番号が重ならないことを足す

受け入れ条件(案)

  1. Factory の確定仕様の間で、同じ番号が別の条件を指さない
  2. 重なりを CI が落とす
  3. 番号を引いている設計文書・確定仕様の参照が、振り直した番号へ追随する

起票者の推定

本文のすべてが起票者の書いた文で、利用者の指示の原文は無い。承認ゲート 1 で利用者が確かめるまで、下の条件を利用者の決定として扱わない。

# 条件 推した出所 この要求での扱い
S1 番号は Factory の確定仕様のすべてで通し番号として振る決まりである docs/specifications/ndf-factory-contracts-and-progress.md の「#2170 の I24 に続けて番号を振る」(今は 385 行目)と、ndf-factory-accounts-and-plans.md 180 行目・ndf-factory-runs-and-runner.md 368 行目の同じ趣旨の文 前提 1
S2 番号の振り方を「ファイルごとの接頭辞(例: DL-I48)」か「真の通し番号」のどちらかに決める 本文の「直し方の案」 未決 1(設計で決める)。受け入れ条件はどちらの方式でも判定できる形にした
S3 重なりの判定は「表の 1 列目の番号」で行う 本文の「直し方の案」 受け入れ条件 4〜7
S4 I8・I9・I10 の 2 ファイルへの出現は再掲で、重なりではない 本文の「何が困るか」 前提 2・受け入れ条件 5。今の文面は再掲の側で書き直されており同じ文ではない(下の「調べた事実」)
S5 番号を引く設計文書・確定仕様の参照を振り直した番号へ追随させる 本文の「受け入れ条件(案)」3 受け入れ条件 8〜9。参照の範囲に Factory のコードのコメントとテストの名前を足した(理由は前提 4)

目的

  • Factory の確定仕様で、不変条件の番号 1 つが 1 つの条件だけを指す状態にする。読み手(設計を書く AI・レビュアー・実装者)が番号だけで条件を引け、引くたびにどのファイルの条件かを書き分けなくてよくなる
  • 確定仕様を足すたびに同じ重なりが起きないように、重なりを継続的統合で止める

調べた事実

e532ac98c(2026-11-06 の develop と同じコミット)で、docs/specifications/ndf-factory-*.md の表の 1 列目にある I<数> をファイルごとに集めた。

cd docs/specifications
for f in ndf-factory-*.md; do
  n=$(grep -oE '^\| *I[0-9]+ *\|' $f | tr -d '| ' | sort -u -V | tr '\n' ' ')
  [ -n "$n" ] && echo "$f: $n"
done
ndf-factory-accounts-and-plans.md: I12 … I24
ndf-factory-contracts-and-progress.md: I10 I25 … I31 I37 I44 I45 I50
ndf-factory-dev-loops.md: I44 … I55
ndf-factory-issue-requests.md: I46 I47 I48 I49
ndf-factory-organizer.md: I56 … I68
ndf-factory-runs-and-runner.md: I8 I9 I32 … I36 I38 … I43
ndf-factory-service-boundary.md: I1 … I11
ndf-factory-sprint-views.md: I1 … I14
番号 出るファイル 判定
I1〜I7・I11 境界の仕様(ndf-factory-service-boundary.md)・スプリントの画面の仕様(ndf-factory-sprint-views.md) 別の条件。重なり
I8・I9 境界の仕様・実行とランナーの仕様(ndf-factory-runs-and-runner.md)・スプリントの画面の仕様 実行とランナーの仕様の行は再掲(「全体の契約のまま」)。スプリントの画面の仕様の行は別の条件で重なり
I10 境界の仕様・受け口と進捗の仕様(ndf-factory-contracts-and-progress.md)・スプリントの画面の仕様 受け口と進捗の仕様の行は再掲。スプリントの画面の仕様の行は重なり
I12〜I14 アカウントと料金プランの仕様(ndf-factory-accounts-and-plans.md)・スプリントの画面の仕様 重なり
I44・I45・I50 受け口と進捗の仕様・開発ループの仕様(ndf-factory-dev-loops.md) 重なり
I46〜I49 開発ループの仕様・起票の依頼の仕様(ndf-factory-issue-requests.md) 重なり

再掲の行は、元の行と文面が同じではない(例: I9 は境界の仕様で「同時に動く実行ジョブは 1 つ」、実行とランナーの仕様で「終わりの状態でない実行ジョブは 1 つまで(実行の currentJobId)」)。文面の一致では再掲と重なりを区別できない。

Factory のコード(factory/)のコメントとテストの名前も番号を引いている。重なる番号を引く行の例:

前提

  • 前提 1: 対象の番号は、Factory の確定仕様(docs/specifications/ndf-factory-*.md)の表のうち、1 列目が I<数> の行の番号である。設計文書が自分の中だけで振る番号(「NDF Factory: 取り込みの衝突(base_conflict)と、複数のループの承認の依頼の一覧が Web の画面に出ない(#2347 の受け入れ条件 7・13 の残り) #2430 の I1」のように課題の番号を添えて引くもの)は対象にしない
  • 前提 2: 別のファイルの条件を書き直して載せる「再掲」は残してよい。再掲は、元の番号と同じ番号を使い、再掲であることを行の中で機械が読める形で示す。示し方は設計で決める
  • 前提 3: 重なりを振り直すときは、重なる番号を持つファイルのうち、片方の番号を今のまま残す。どちらを残すかは設計で決める
  • 前提 4: 番号の参照は、確定仕様・issues/ 直下の設計文書と要求のコピー・Factory のコードのコメントとテストの名前にある。どれも番号で条件を引くため、取り残すと別の条件を指す
  • 前提 5: 重なりの検査は、リポジトリの検査のスクリプトを置く scripts/ に置き、既存の継続的統合のジョブから呼ぶ。NDF のプラグインの配布物(plugins/)には入れない
  • 前提 6: 1 ファイル 500 行の上限(scripts/check-doc-line-limit.py)を守る。境界の仕様は今 500 行で、行を足す変更は同じファイルの中で行を減らすか分割が要る

対象範囲

含む:

  • Factory の確定仕様の間で重なる不変条件の番号の振り直し(上の「調べた事実」の重なり)
  • 番号の振り方の決まりを 1 か所に書き、ほかのファイルの「〜に続けて番号を振る」の文をその場所への参照にすること
  • 重なりを見つけると失敗する検査と、その検査を継続的統合で動かすこと
  • 振り直した番号を引く参照の追随(確定仕様・issues/ 直下の設計文書と要求のコピー・factory/ のコメントとテストの名前)

含まない:

  • issues/old/ の文書と、閉じた課題・Pull Request の本文の番号(書いた時点の記録として残す)
  • 設計文書が自分の中だけで振る番号(前提 1)
  • Factory 以外の確定仕様(docs/specifications/ のほかのファイル)の番号の振り方
  • 不変条件の中身(条件の文・破れたときの扱い)の変更
  • 古い参照が残っていないかを機械で見つける検査(通し番号の方式では、古い番号が別の条件の正しい番号でもあるため機械で区別できない。追随は受け入れ条件 9 の一覧で確かめる)

ドメインイベント

# イベント 引き金 失敗したとき 順序の前提
E1 確定仕様に不変条件の行が足された 設計の確定仕様化(plan-to-spec)か、手で確定仕様を直す Pull Request 重なる番号の行が足される → E2 で落ちる —
E2 継続的統合が番号の重なりを検査した Pull Request の作成・更新 重なりがあれば失敗し、番号とファイルを出す。検査が表を読めないときは重なり無しとして通さない(受け入れ条件 7) E1
E3 重なる番号を振り直した この課題の実装 振り直した番号が別の条件と重なる → E2 で落ちる 番号の方式が決まっている(未決 1)
E4 振り直した番号の参照を追随させた E3 取り残した参照は機械で見つからない → 受け入れ条件 9 の一覧で見る E3

用語

用語 意味
不変条件 集約がいつも満たす条件(用語集の意味)。この文書では、Factory の確定仕様の表に I<数> の番号付きで載るものを指す
再掲 Factory の確定仕様で、別のファイルの不変条件を同じ番号のまま書き直して載せた行
番号の重なり 再掲でないのに、Factory の 2 つの確定仕様の別の不変条件が同じ番号を持つこと

受け入れ条件

  • 1. e532ac98c で重なる番号(I1〜I14・I44〜I50 のうち上の表で「重なり」のもの)が、振り直しの後はそれぞれ 1 つの条件だけを指す
  • 2. 番号の振り方の決まり(方式と、次に振る番号の求め方)が 1 か所に書かれ、ほかの Factory の確定仕様の「〜に続けて番号を振る」の文はその場所を指す
  • 3. 不変条件の中身(条件の文と破れたときの扱いの列)は、番号と再掲の印を除いて振り直しの前と同じである
  • 4. 検査を振り直しの後の docs/specifications/ に対して実行すると、終了コード 0 で終わる
  • 5. 検査は、I8・I9・I10 のように再掲の印を持つ行を重なりと判定しない
  • 6. 2 つの Factory の確定仕様に、再掲の印の無い同じ番号の行を置いて検査を実行すると、0 以外の終了コードで終わり、その番号と 2 つのファイルのパスを出す
  • 7. 再掲の印を持つのに、元の番号がどの Factory の確定仕様にも無い行があると、検査は 0 以外の終了コードで終わる
  • 8. 検査が継続的統合のジョブとして Pull Request ごとに動き、受け入れ条件 6 の入力の Pull Request ではそのジョブが失敗する
  • 9. 振り直した番号ごとに、古い番号を引いていた箇所の一覧(検索のコマンドと結果)と、それぞれをどの番号へ直したか・直さなかった理由が実装の Pull Request の本文にある。一覧の対象は前提 4 の範囲である
  • 10. 振り直しの後、factory/ のテスト(factory-check のジョブ)と既存の検査(check-markdown-links.py・check-doc-line-limit.py)が通る(退行しない)

非機能の条件

大項目 条件
運用・保守性 検査の失敗の出力だけで、どの番号をどのファイルで直せばよいかが分かる(受け入れ条件 6)

影響

対象 影響
公開インタフェース 変わらない。プラグインの配布物と Factory の API は変えない
データ 変わらない
既存の振る舞い 確定仕様と設計文書の番号の参照が変わる。継続的統合に検査が 1 つ増える

検証手段

項目 手段
テスト 検査のスクリプトのテスト(重なり・再掲・元の無い再掲・重なり無しの入力)を uv run --frozen --project . --all-extras pytest scripts/tests -q で動かす
静的解析・型検査 python3 scripts/check-markdown-links.py --root .・python3 scripts/check-doc-line-limit.py。Factory のコメントを直したら factory-check のジョブ
手動確認(マージ前) 受け入れ条件 9 の一覧を、レビュアーが番号ごとに 1 件以上開いて、直した先の番号が同じ条件を指すことを見る

前提とする取り決め

項目 参照先 / 決めたこと
プロジェクト構造 確定仕様は docs/specifications/、リポジトリの検査は scripts/ とそのテスト scripts/tests/(AGENTS.md)。plugins/ と factory/ の振る舞いは変えない
コーディング規約 AGENTS.md の「最小限のコード実装」。.md の文言を照合するテストは書かない(検査のテストは一時ディレクトリに置いた入力で振る舞いを見る)
テスト戦略 検査のスクリプトを単体テストで見る。番号の追随はテストでは見ず、受け入れ条件 9 の一覧で見る

境界

区分 内容
常に行う 番号を振り直した行の参照を、前提 4 の範囲で検索して直す。既存の検査を通す
確認してから行う 番号の方式の決定(承認ゲート 1 で人が見る)
行わない 不変条件の中身の変更、issues/old/ と閉じた課題の本文の書き換え、Factory 以外の確定仕様の番号の振り直し

未決

項目 誰が決めるか 期限
1. 番号の方式(ファイルごとの接頭辞か、すべての Factory の確定仕様で通し番号か) 設計(承認ゲート 1 で利用者が確かめる) 設計の承認まで
2. 重なる 2 つのファイルのどちらの番号を残すか(前提 3) 設計 設計の承認まで
3. 再掲の印の形(前提 2) 設計 設計の承認まで
4. 検査を呼ぶ継続的統合のジョブ(既存のジョブへ足すか、新しいジョブか) 設計 設計の承認まで

進行

モード: —

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

Activity

  1. changed the title [-]Factory の確定仕様で不変条件の番号(I8〜I10・I44〜I50)が重なり、同じ番号が別の条件を指す[/-] [+]Factory の確定仕様で不変条件の番号 I44〜I50 が重なり、同じ番号が別の条件を指す[/+] on Nov 2, 2026
  2. added a commit that references 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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions