Skip to content
frontmatter
キー値
specdojo.idprj-0001:pjr-qhka-docs-structure-detached-unit
specdojo.typeproject
specdojo.statusready
specdojo.rulebookspecdojo:pjr-rulebook
specdojo.part_ofprj-0001:pjr-index
specdojo.item_typetodo
specdojo.item_statusdone
specdojo.prioritymedium
specdojo.ownerARC
specdojo.registered_at2026-09-02T22:48:28Z
specdojo.due_on2026-09-30
specdojo.completed_at2026-09-12T06:00:02Z
specdojo.conclusiondocs-structure-guide に別リポジトリ構成(Detached Unit)の章を追記し、採用条件、ディレクトリレイアウト、result への app commit hash 記録によるトレーサビリティ方式を規定した。

PJR-QHKA 別リポジトリ構成(Detached Unit)のドキュメント化 ​

1. 概要 ​

SpecDojo の成果物をプロダクトと同じリポジトリに置かず、別リポジトリ(app1-specdojo/)で 運用する構成を docs-structure-guide.md へ追記する。採用条件、ディレクトリレイアウト、 result への app commit hash 記録によるトレーサビリティ方式を規定する。

現在のガイドは同一リポジトリ構成だけを前提としており、別リポジトリ構成の記述がない。

2. 方案の評価 ​

2.1. 想定する構成 ​

プロダクトと SpecDojo をリポジトリで分け、SpecDojo 側から開発を管理する。

text
app1/                 プロダクト(別リポジトリ)
app1-specdojo/        SpecDojo(別リポジトリ)。npm i -D specdojo で CLI を入れる
app1-worktrees/       worktree の置き場

動機はプロダクトリポジトリの見通しを良くすることである。SpecDojo は1つの登録簿項目につき start / wait / review / close の遷移 commit と統合 commit を生み、成果物の更新も加わる。 プロダクトの変更履歴を追う目的からは雑音になる。物量も大きく、本リポジトリでは kata だけで 301文書ある。

2.2. 成立を支える実装上の事実 ​

要素実装
ルート決定.specdojo/ の位置から上方探索する。git には依存しない
パス解決specdojo.config.json が相対パスで宣言する
リポジトリ外拒否grade と register にはあるが、exec の実行系にはない
親検証cwd を引数で受ける(invoke(definition, cwd))
親検証の内容npm run test:unit など。実行場所が変われば対象も変わる

exec の実行系にリポジトリ外を拒否するガードはなく、親検証も cwd を受け取る設計である。 構成として原理的に不可能ではない。

2.3. 現状で未対応の点 ​

一方、次は単一リポジトリを前提としており、多リポジトリでは追加の対応が要る。

論点現状
編集対象の解決job の paths と task の targets は SpecDojo ルート相対
worktree の隔離SpecDojo リポジトリの worktree を作る。プロダクト側は隔離外
commit のスコープSpecDojo リポジトリに対して計算する。プロダクト側の commit 主体が未定義
親検証の実行場所SpecDojo ルートで実行する。プロダクトへ向ける設定がない

worktree の置き場を分けても、隔離されるのは SpecDojo 側だけである。agent がプロダクトを 編集すると、その変更は隔離の外に出る。並行実行と失敗時のロールバックが効かない。

2.4. product docs の配置 ​

プロダクトの docs をどちらへ置くかは、SpecDojo が管理するかどうかで決まる。本リポジトリの 実態は次のとおりである。

指標実測
成果物カタログ(dct-*.yaml)28 件
うち docs/ja/product を指すもの21 件

カタログは base_path: /docs/ja/product/... の形で product docs を成果物として宣言する。 deliverable scaffold が雛形を生成し、exec が編集し、grade が評価する対象である。

つまり product docs は「プロダクトの付属文書」ではなく、SpecDojo が管理する成果物そのもので ある。app1/docs/ja/product へ置くと、SpecDojo の中核である catalog / exec / grade がリポジトリを またぐことになり、最も更新頻度の高い文書がすべて多リポジトリ対応を必要とする。

配置評価
app1/docs/ja/product分離の利点が小さく、対応コストが大きい
app1-specdojo/docs/ja/productcatalog / exec / grade が単一リポジトリで閉じる

app1-specdojo/ 側を推す。プロダクトリポジトリの見通しを良くする目的にも合致する。文書を プロダクト側へ残すと、見通しの改善そのものが薄まる。

ただしトレードオフがある。プロダクトの実装と設計文書が別リポジトリになるため、実装変更と 文書更新が1つの commit にまとまらない。README や API リファレンスなど、プロダクト利用者が コードと同じ場所で読むべき文書は app1/ に残す判断があり得る。SpecDojo が成果物として管理する 文書と、プロダクトに付属する文書を分けて考える。

2.4.1. 再検討: src との同期という観点(2026-09-10) ​

2.4. は「SpecDojo が管理する成果物だから SpecDojo 側へ置く」という論理で判断した。管理主体を 基準にしている。src との同期が必要かという観点が欠けていた。実測を追加する。

src と docs/ja/product を同じ commit で変更した回数を直近 60 日で数えた。

区分件数
src と product を同時変更24
src のみ162
product のみ128

同時変更の内容は実装と設計文書が一体のものである。

text
a8deb72c  job のコマンド実行を決定論的にする   → src/job.ts + sysd-job-execution.md
2a243d26  routine の action.kind を job へ統合 → src/routine.ts + 設計文書
2e9e24a5  実行の同一性を period から組み立て…  → src + product docs

実装を変えれば設計文書も変わる。PJR-GWY4 では src/job.ts と docs/ja/product/040-system-design/sysd-job-execution.md を同じ commit で変更した。

24 回の同時変更は、切れない結合の証拠である。別リポジトリにすると、この 24 回が 2 つの commit に分かれ原子性を失う。

状況結果
src を統合、docs の統合が失敗実装と設計が食い違った状態で残る
片方だけ revert整合が崩れる
特定バージョンの設計を読む2 つのリポジトリの版を突き合わせる必要がある

2.4.2. 量で判断すると見誤る ​

docs/ja/product の commit は直近 30 日で 88 件、全体 1007 件の 9% である。量だけ見れば分離の 影響は小さく見える。これは結合の質を見ていない。

一方 docs/ja/projects は 834 件で 83% を占め、src と連動しない。register の起票・遷移と exec の plan / result / evidence が積み上がるためである。commit 頻度の問題はこちらに起因する。

領域commit/30 日src との同期
docs/ja/projects834不要
docs/ja/specdojo154不要
docs/ja/product88必要
src107—

2.4.3. 境界の引き方 ​

同期の観点を採ると、境界は「同期が必要か」で引かれる。

text
app1/           ← src + docs/ja/product(同期が必要な対)
app1-specdojo/  ← docs/ja/projects + docs/ja/specdojo(SpecDojo の運用記録)

管理主体で引く 2.4. の案より、この方が結合の実態に合う。プロダクトリポジトリの commit 頻度を 抑える目的も、docs/ja/projects の 834 件を分離することで達成される。

2.4.4. 前提条件は変わらない ​

ただし 2.4. で挙げた障害は消えない。

課題内容
catalog の 78% が境界を越える27 件中 21 件が docs/ja/product を指す
exec run --worktree二重 worktree が必須になる
grade --target deliverable別リポジトリを読む必要がある

2.5. の二重 worktree は将来構成として整理したもので、実装は未了である。この配置を採るなら 二重 worktree の実装が前提条件になる。

2.4.5. 判断の状態 ​

同期の観点は 2.4. の判断を覆す根拠になりうる。ただし配置の変更は二重 worktree の実装を要し、 影響が大きい。本項では実測と論点の記録に留め、配置の確定は別途行う。

2.5. 二重 worktree による並行実行 ​

docs とソースの両方を1つの登録簿項目で扱う場合、両リポジトリの worktree を app1-worktrees/ 配下へ作り、app1-specdojo/ の specdojo コマンドが両方を管理する構成が考えられる。

text
app1-worktrees/
  <task-id>/
    docs/     app1-specdojo の worktree
    src/      app1 の worktree

2.5.1. 実装が許す部分 ​

ensureExecWorktree は repoRoot を引数で受け取る。特定のリポジトリに固定されていないため、 同じ関数で別リポジトリの worktree を作れる。

text
ensureExecWorktree({ repoRoot, worktreeBase, taskId, ... })

worktreeBase はリポジトリ外であることを要求する。app1-worktrees/ は両リポジトリの外にあり、 この制約を満たす。branch 名は task ID から決まるため、両リポジトリで同じ名前を使える。

2.5.2. 単一リポジトリを前提とする部分 ​

統合処理は repoRoot と worktree.path の2つだけを文脈として持ち、1組の対応関係を前提とする。

処理現状
commit 対象repoRoot に対して算出する
merge 先repoRoot で checkout 中のブランチ
比較基準merge-base HEAD <rootHead> を repoRoot と worktree で取る
pipeline-statetask_id と run_id で1つ。リポジトリの区別を持たない

二重 worktree にすると、これらがすべて2組必要になる。

2.5.3. 統合順序と部分状態 ​

docs とソースの両方を扱う項目では、ソースを先に統合し、成功した場合だけ docs を統合する。 この順序により、起こり得る部分状態は1通りに定まる。

失敗箇所結果扱い
ソースの統合両方とも未統合清潔。項目全体を再実行する
docs の統合ソースのみ統合済みdocs の統合だけを再試行する

任意の部分状態が生じるわけではないため、分散トランザクションのような一般的な回復手順は要らない。 回復に必要な仕組みは既にある。

  • 統合段のみの再試行は exec run --resume が担う。executor と reporter が成功済みで統合だけが 失敗した run を、agent を起動せず統合から再開する。
  • 統合済みブランチの再 merge は isExecBranchMergedIntoCurrent が防ぐ。ソースを二重に統合しない。

ソースを先に統合する順序は、プロダクトの完全性を優先する点でも妥当である。SpecDojo 側の失敗が プロダクトへ波及しない。

2.5.4. 定義が必要な事項 ​

部分状態そのものは扱えるが、次は運用上の定義を要する。

  • 部分状態での item_status。ソース統合済みで docs 未統合の項目は waiting とする。完了条件を 満たしておらず、再開で docs の統合だけを行うためである。review にすると実質完了として扱う ことになり、未統合の docs が追跡から外れる。
  • 打ち切ったときの後始末。docs の統合が繰り返し失敗して項目を諦める場合、ソースは統合済みの まま残る。放置するか revert するかを決める必要がある。ただしこれは通常の merge 後の判断と同じ であり、二重 worktree に固有の問題ではない。
  • 並行実行時の履歴順序。複数項目を並行実行すると、A のソース統合、B のソース統合、A の docs 統合という順序が起こり得る。各リポジトリ内では直列化されるため衝突しないが、A のソースと A の docs の間に B が入る状態は生じる。履歴を追うときの前提になる。

2.5.5. 実装が必要な事項 ​

順序化で解ける課題とは別に、次は実装を要する。

  • 親検証の割り当て。test-unit はソース側、lint:md と validate:schema は docs 側で実行する 必要がある。現在の親検証は cwd を1つしか持たないため、検証 ID ごとに実行先を宣言する仕組みが 要る。
  • agent の作業ディレクトリ。agent は両方を見る必要がある。app1-worktrees/<task-id>/ を cwd に すれば両方が相対パスで見えるが、paths と targets の解決基準が「リポジトリルート相対」から 「タスク作業ディレクトリ相対」へ変わる。既存の単一リポジトリ実行と規則が分岐する。
  • 失敗時の worktree 保持。現在は失敗した worktree を残して調査に使う。二重化した場合に どちらをどの条件で残すかを定める。
  • 統合処理の複製。commit 対象の算出、merge 先の決定、pipeline-state の記録は repoRoot と worktree の1組を前提とする。2組を扱えるようにする。

2.5.6. 評価 ​

構成として成立する。ensureExecWorktree が repoRoot を引数化しており、統合順序を定めれば 部分状態も1通りに収まる。回復に必要な統合段の再試行と再 merge の防止は既に実装済みである。

残るのは実装量と、上記の運用定義である。設計上の障害は見当たらない。

段階を分ける余地はある。docs のみを扱う項目(実装を伴わない要件・設計・計画の更新)であれば 統合先が1つで済み、二重 worktree の実装を待たずに別リポジトリ構成を試せる。

本項目は設計の整理までとするため、実装は範囲に含めない。ガイドには構成案、統合順序、部分状態の 扱い、未実装の事項を記載し、採用可否の判断材料を残す。

2.6. 複数のプロダクトリポジトリを管理する ​

1つの SpecDojo リポジトリが複数のプロダクトリポジトリを管理できる。

text
app1/              プロダクト
app1-marketing/    マーケティング
app1-specdojo/     SpecDojo(両方を管理)
  docs/ja/projects/prj-app1/
  docs/ja/projects/prj-marketing/

2.6.1. 現状の設計で成立する ​

specdojo.config.json の projects は複数のプロジェクトを保持する。

typescript
export type SpecDojoConfig = {
  version: 1;
  current_project?: string;
  projects: Record<string, SpecDojoProjectConfig>;
};

各プロジェクトのパスは base_path を起点に組み立てられ、プロジェクトごとに独立する。すべての コマンドが --project <id> を受け取り、解決順序も定義済みである。

text
1. --project <id>
2. 環境変数 SPECDOJO_PROJECT
3. current_project
4. projects の先頭

プロダクトごとにプロジェクトを分ければ、成果物、登録簿、実行記録がそれぞれ独立する。

2.6.2. 未対応の範囲 ​

1つの登録簿項目が複数のプロダクトリポジトリを同時に変更する場合は成立しない。二重 worktree の 課題が組み合わせの分だけ増える。

論点プロダクト1つプロダクト複数
worktree の隔離2 組(docs と src)3 組以上
統合の順序src の次に docsどの src を先にするか
親検証実行先が 2 つリポジトリごとに異なる
部分状態1 通り組み合わせの分だけ増える

統合順序が定まらないと部分状態が一意にならない。2.5.3. 統合順序と部分状態 で示した回復手順が そのままでは使えない。

ただし実務上この状況は稀と考えられる。プロダクトとマーケティングの成果物を同一項目で変更する 場面は限定的で、項目をプロジェクト単位に分ければ回避できる。

対応は prj-0001:pjr-p7hy-multi-repo-single-item として分離する。

2.6. 適用範囲の整理 ​

構成評価
文書のみを扱う(自己完結)現状の実装で成立する
プロダクト駆動(本方案)設計上あり得るが、多リポジトリ対応の実装が要る
SpecDojo 自身の開発(本リポジトリ)成果物と実装が同じ変更で動くため同一リポジトリ

本項目は設計の整理までとし、多リポジトリ対応の実装は範囲に含めない。ガイドには構成の紹介と あわせて、未対応の点と適用条件を明記する。

3. 完了条件 ​

  • docs-structure-guide.md に「別リポジトリ構成(Detached Unit)」の節がある。
  • app1/ / app1-specdojo/ / app1-worktrees/ のレイアウト例が記載されている。
  • product docs の配置判断と根拠が示されている。プロダクトに残す文書との切り分けも記載する。 ガイドの記述は SpecDojo 側へ置く前提だが、再検討: src との同期という観点 により見直しの 余地がある。配置を変更する場合はガイドも追従させる。
  • 現状で未対応の点(編集対象の解決、worktree の隔離、commit のスコープ、親検証の実行場所)が 明記されている。
  • result への app commit hash 記録によるトレーサビリティ方式と、片方向であること、記録時点の 定義が記載されている。
  • 二重 worktree による並行実行の構成案が記載されている。ソースを先に統合する順序、生じ得る 部分状態、部分状態では waiting とすることが示されている。
  • 二重 worktree で実装を要する事項(親検証の割り当て、agent の作業ディレクトリ、失敗時の worktree 保持、統合処理の複製)が記載されている。
  • 適用条件が明記されている。文書のみを扱う構成と、プロダクト駆動の構成を区別する。
  • npm run -s lint:md が通る。

4. 作業内容 ​

No作業担当状態メモ
1構成の概要とディレクトリレイアウトを記述するARCdone3ディレクトリ構成
2product docs の配置判断と根拠を記述するARCdoneカタログ28件中21件が指す
3未対応の点を記述するARCdone隔離とcommitスコープ
4トレーサビリティ方式と限界を記述するARCdone片方向、記録時点
5二重 worktree の構成案と統合順序を記述するARCdone部分状態は waiting
6適用条件を記述するARCdone自己完結型と駆動型を区別
7lint を確認するARCdoneMarkdown 検査実施
8履歴改変に耐える主参照を規定するARCdoneitem ID の Refs trailer
9rebase / squash 後の確認手順を規定するARCdone統合先の Git 履歴を確認
10既存 hash 記録の移行方針を規定するARCdonePR と最終 hash を追記

5. 対応結果 ​

  • specdojo:docs-structure-guide に「別リポジトリ構成(Detached Unit)」を追加した。

  • 初回対応では、3ディレクトリの配置、プロダクト文書の切り分け、現行実装の境界、result から app commit への片方向トレーサビリティを規定した。

  • 二重 worktree は将来構成として、app 側を先に統合する順序、部分状態での waiting、採用前に必要な実装を明記した。多リポジトリ対応の実装自体は本項目の範囲外である。

  • 受け入れ時に orchestrator が lint:md と docs:build の通過を確認した。

  • 初回対応では、app commit hash を統合後に確定してから docs 側の result へ記録する手順まで 具体化した。この方式の欠陥と再開後の置き換えは 5.1. と 5.2. に記録する。

  • 残課題は二重 worktree の実装(親検証の割り当て、agent の作業ディレクトリ、失敗時の worktree 保持、統合処理の複製)である。本項目は設計の整理とガイド追記までとする。

5.1. 再開: トレーサビリティ方式の欠陥 ​

2026-09-08 に reopen した。10.5. result によるトレーサビリティ で規定した commit hash による 参照が、標準的な運用で目的を果たさない。

5.1.1. 欠陥の内容 ​

ガイドは限界を認めている。

text
履歴改変によって hash が到達不能になる可能性と、参照の整合性を自動検証しない制約を
受け入れる必要があります。

この判断が弱い。理由は3点ある。

squash merge は例外ではない。GitHub の PR で squash merge を選ぶ運用は広く使われる。稀な 履歴改変ではなく、標準的なワークフローで必ず新しい commit が生成される。

失敗が静かで回復できない。hash が変わるだけでなく、元の commit が到達不能になれば GC で 削除される。squash merge 後にブランチを削除する運用では参照先そのものが消え、git show は 失敗する。何を指していたかを知る手段が残らない。警告は出ず、追跡しようとした時に初めて分かる。

記録時点が squash と噛み合わない。ガイドは app 側の統合成功後、SpecDojo 側の統合前に記録 すると定める。PR ベースの squash では最終的な commit がその後に生成されるため、記録した hash は統合先ブランチに載る commit と一致しない。SpecDojo 側は統合済みであり、後から更新する運用は 成立しない。

5.1.2. 根本原因 ​

ガイドは逆参照を意図的に排除している。

text
app1/ 側の commit message やファイルに SpecDojo result への逆参照を必須とせず

これは「アプリの commit 履歴を汚さない」という Detached Unit の目的から導かれた選択である。 目的としては正しいが、hash はリポジトリの履歴操作に従属する識別子であり、履歴と独立した 識別子を持たない限り履歴改変に耐えられない。

「汚さない」と「追跡できる」は hash だけでは両立しない。

5.1.3. 対処の方向 ​

案履歴改変への耐性
現状維持なし
commit message へ trailer高い
PR 番号・URL を記録高い
app 側に tag を打つ中

commit message への trailer を主軸とし、PR 番号を併記する案を推す。

text
feat(auth): トークン失効処理を追加する

Refs: PJR-XXXX

識別子が内容とともに移動するため、rebase では message が保持され、squash でも既定では各 commit の message が連結される。git log --grep で hash に依存せず追跡できる。Gerrit の Change-Id が同じ問題に対して採る方式である。汚染は commit message 1 行にとどまり、ファイルは 追加されない。

hash は記録時点のスナップショットとして残す価値はあるが、主たる参照にはできない。

5.1.4. 再開後の完了条件 ​

  • 履歴改変を経ても追跡できる識別子が主たる参照として規定されている。
  • squash merge と rebase を経た場合に追跡できることを、手順として確認できる。
  • 逆参照を必須としない現在の規定との関係が整理されている。アプリの履歴へ何をどこまで 書き込むかの判断根拠が示されている。
  • 既に記録済みの hash がある場合の移行方針が示されている。
  • 10.5. の暫定注意書きが解消されている。

5.2. 再開後の対応結果 ​

  • 主たる参照を commit hash から登録簿 item ID へ変更し、app の commit message に Refs: PJR-XXXX trailer を残す規則を設けた。PR 参照と40文字の最終 commit hash は、レビュー 経緯と確認時点を固定する補助情報として result 本文へ記録する。
  • rebase 後は書き換え後の対象 commit、squash merge 後は最終 commit の message を確認する手順を 追加した。squash 時の自動的な message 連結には依存せず、統合先ブランチで git log --grep を 実行して item ID を検索できることを SpecDojo 側の統合前に確認する。
  • 「app 側への逆参照は不要」という旧規定を改め、app のファイルや状態遷移は増やさない一方、 commit message 1行の Refs: trailer は必須とした。Detached Unit の履歴分離を維持しつつ、hash だけでは失われる追跡可能性を確保するためである。
  • 既存 result の hash は削除せず、到達可能性と PR を調べて item ID、PR、最終 hash を追記する移行 方針を定めた。共有済み app 履歴の書き換えは禁止し、特定できない対応は推測せず未解決として 記録する。
  • これにより 10.5. の暫定注意書きを解消し、再開後の完了条件を満たした。二重 worktree の実装は 引き続き本項目の範囲外である。

6. 関連ドキュメント ​