Imported from moorestech/moorestech (
.agents/skills/writing-plans/SKILL.md). Install upstream withnpx skills add moorestech/moorestech --skill writing-plans. Copyright stays with the author.
Writing Plans
概要
このコードベースについて前提知識ゼロのエンジニアを想定して、包括的な実装計画を書く。各タスクでどのファイルを触るか、コード、テスト、確認すべきドキュメント、テスト方法まで、必要なことをすべて記述する。plan全体を一口サイズのタスクとして渡す。DRY。YAGNI。タスクごとにコミット。
対象は熟練の開発者だが、このツールセットや問題ドメインについてはほぼ何も知らないと想定する。
前提(plan記述前): planは最新の origin/master を土台にした作業ブランチで書く。ブランチの用意は環境ローカル規約に従う(例: CLAUDE.local.md の使い捨てworktree moores-wt new。fetch済みの土台を作る)。古いコードを前提にしたplanは実装時に破綻するので、土台がmasterから遅れていればplanを書き始めずユーザーに報告する。
plan保存先: docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md
- (plan保存場所についてユーザーの指定がある場合はそちらを優先)
Scope Check
要件が複数の独立したサブシステムにまたがる場合、設計セッション(grill)の段階でサブプロジェクトごとに分割されているはず。分割されていなければ、サブシステムごとに別々のplanへ分けることを提案する。各planはそれ単体で動作しテスト可能なソフトウェアを生み出すべき。
File Structure
タスクを定義する前に、どのファイルを新規作成・変更するか、各ファイルが何の責務を持つかをマップしておく。ここで分解の判断が固まる。
- 明確な境界と定義済みのインターフェースを持つ単位として設計する。各ファイルは明確な単一責務を持つべき。
- 一度にcontextへ収まるコードほど的確に推論でき、ファイルが焦点を絞られているほど編集の信頼性が上がる。何でもやる大きなファイルより、小さく焦点を絞ったファイルを優先する。
- 一緒に変わるファイルは一緒に置く。技術レイヤーではなく責務で分割する。
- 既存のコードベースでは、確立されたパターンに従う。コードベースが大きなファイルを使う流儀なら独断で再構成しない。ただし変更対象のファイルが肥大化している場合は、planに分割を含めるのは妥当。
この構造がタスク分解の指針になる。各タスクは、それ単体で意味の通る自己完結した変更を生み出すべき。
Task Right-Sizing
タスクとは、それ自体のテストサイクルを持ち、新規レビュアーのゲートに値する最小単位である。タスクの境界を引く際は、セットアップ・設定・足場・ドキュメント作成のステップは、それを必要とする成果物のタスクへ畳み込む。分割してよいのは、あるタスクを却下しつつ隣のタスクを承認することがレビュアーにとって意味を持つ場合のみ。各タスクは独立してテスト可能な成果物で終わる。
Step Granularity
各ステップは1アクション(テストを書く/実装する/テストを実行して結果を確認する/コミットする)。RED→GREENの順序は要求しない(AGENTS.md はTDDを要求していない)。
Plan Document Header
spec文書は作らない。 設計セッション(moores-grill-with-docs)の成果はADR(docs/adr/)と用語集であり、要件は本plan先頭の ## Requirements セクションに書く。判断台帳はplan末尾の『## 判断記録(ADR)』が正で、ledger-gateもそれを読む(旧planのfrontmatter spec: は互換のため、解決できればspec側台帳も連結して検査される)。
必ずこのヘッダーから始める:
# [Feature Name] Implementation Plan
> **For the controller session (実装を担うsubagentはこのブロックを無視してよい):** このplanの実行は subagent-driven-development スキルが担う。実行モード(規模ゲート未満の単一subagent実装モード/閾値超のタスクごと派遣)は同スキルの規模ゲートに従って決める。ステップはチェックボックス(`- [ ]`)記法で書く。
**Goal:** [これが何を構築するかを1文で説明]
**Architecture:** [アプローチについて2〜3文]
**Tech Stack:** [主要な技術/ライブラリ]
## Requirements
[設計対話(grill)で確定した要件を列挙する。1行1要件・各行に受け入れ基準を含める。
「やらないこと」(スコープ境界)も明記する。planning着手時に最初に書き出すこと —
このセクションがSelf-Reviewのカバレッジ検査の照合表になる]
## Global Constraints
[プロジェクト全体の要件 — バージョン下限、依存関係の制限、
命名・表記のルール、プラットフォーム要件 — Requirementsと設計ADRから
正確な値を逐語的に記載する。すべてのタスクの要件は暗黙的に
このセクションを含む]
---
Final tasks (moorestech, required): every plan's task list ends with an explicit closing task pair — 実行者はこれを無条件に実行する。planから省略しても ゲートは免除されない(subagent-driven-developmentのmandatory-gateセクション参照):
- 「必ずmoores-code-reviewスキルで全ブランチレビューを実行すること (自動実行・ゴール文言による省略不可)」
- 「セッション終了可能状態にすること: pr-createスキルでPRを作成し、 masterとのコンフリクトがあればmasterをマージして解消・コンパイル確認のうえpushする (解消の実作業はpr-create経由でopus subagentに委譲される)。 全作業がコミット・push済みで、このセッションをそのまま閉じてもPRがマージ可能な 状態になっていることを確認して終える」。全実装タスク完了=完了ではない。 PR未作成のまま終わるのはplan未完了である。
レビュー指摘の反映がソースの判定経路・条件式・その評価時点に触れたら、閉じタスク1の中で plan 内のunityプレイ録画テスト(無ければ EditModeInPlayingTest)を反映後のバイナリで 再実施してから完了とする。ユニットテスト通過・ログ無音は代替にならない(実例 2026-09-05 別プロジェクト: レビュー反映後に e2e を再実施せず、2 日間の機能停止を見逃した較正)。
unityプレイ録画テストの実行を検討する(moorestech, required check): plan作成時、
ランタイム挙動(ゲームプレイ・入力・カメラ・UI・エンティティ表示等)に触れる変更なら、
ユニットテストに加えてunityプレイ録画テスト(unity-playmode-recorded-playtestスキル。
PlayModeを録画付きで通しプレイ検証するもの。「PlayModeテスト」と曖昧に書かず必ずこのスキル名で指す)
をタスクとしてplanに含めるか必ず検討する。録画付き通し検証まで不要な場合の軽量代替は
EditModeInPlayingTest(editmode-in-playing-testスキル・uloop run-testsで実行)。
含めない場合はその判断理由を ## 判断記録(ADR) に1行残す(無言の省略は禁止)。
Task Structure
### Task N: [Component Name]
**Files:**
- Create: `moorestech_server/Assets/Scripts/Exact/Path/NewClass.cs`
- Modify: `moorestech_client/Assets/Scripts/Exact/Path/Existing.cs:123-145`
- Test: `moorestech_server/Assets/Scripts/Tests/Exact/Path/NewClassTest.cs`
**Interfaces:**
- Consumes: [このタスクが前段のタスクから使うもの — 正確なシグネチャ]
- Produces: [後段のタスクが依存するもの — 正確な関数名、引数と戻り値の型。
タスクの実装者は自分のタスクしか見ないため、隣接タスクが使う名前・型を
知る手段はこのブロックだけである]
- [ ] **Step 1: テストを書く**
```csharp
[Test]
public void SpecificBehavior()
{
var result = target.Function(input);
Assert.AreEqual(expected, result);
}
```
- [ ] **Step 2: 実装を書く**
```csharp
public Result Function(Input input)
{
return expected;
}
```
- [ ] **Step 3: コンパイルしテストを実行して通ることを確認する**
Run: `uloop compile --project-path ./moorestech_client` → `uloop run-tests --project-path ./moorestech_client --filter-type class --filter-value "Namespace.NewClassTest"`
Expected: ErrorCount 0 / PASS
- [ ] **Step 4: コミットする**
```bash
git add <Files節のパス>
git commit -m "feat: <specific feature>"
```
判断台帳掲載義務(機械的下限): タスクの Modify:/Create: 対象が .claude/skills/moores-code-review/lenses/*.md の paths 正規表現にマッチする場合、その改修判断はplanの『## 判断記録(ADR)』への掲載が必須(級の自己判定によらない)。未掲載は ledger-gate(Stop hook)がブロックする。掲載なき判断はレビュー免責力を持たない。カバー範囲はpaths発火型レンズのみ — keywords発火型の観点はレビュー段階のsuppressed規則で捕捉される。Files節の対象は必ずリポジトリ相対パスで書く(裸のクラス名だけの表記はゲートの検査対象から漏れる)。
No Placeholders
各ステップにはエンジニアが必要とする実際の内容を含めなければならない。以下はplanの失敗であり、絶対に書いてはならない:
- 「TBD」「TODO」「後で実装」「詳細は後で埋める」
- 「適切なエラーハンドリングを追加」「バリデーションを追加」「エッジケースに対応」
- 「上記についてテストを書く」(実際のテストコードなし)
- 「Task Nと同様」(コードを再掲する — エンジニアはタスクを順不同で読む可能性がある)
- 何をすべきかを説明するだけでどうやるかを示さないステップ(コードステップにはコードブロックが必須)
- どのタスクにも定義されていない型・関数・メソッドへの参照
Remember
- 常に正確なファイルパス
- 各ステップに完全なコードを — ステップがコードを変更するなら、そのコードを示す
- 期待される出力付きの正確なコマンド
- DRY、YAGNI、タスクごとにコミット
Self-Review
完全なplanを書き終えたら、## Requirements と設計ADRを新鮮な目で見直し、planと突き合わせる。これは自分自身で実行するチェックリストであり、subagentへの委譲ではない。
1. Requirements coverage: ## Requirements の各行をざっと確認する。それを実装するタスクを指し示せるか?漏れがあれば列挙する。
2. Placeholder scan: 上記「No Placeholders」セクションのパターンに該当する危険信号がないか、planを検索する。見つけたら修正する。
3. Type consistency: 後段のタスクで使った型・メソッドシグネチャ・プロパティ名は、前段のタスクで定義したものと一致しているか?Task 3ではclearLayers()、Task 7ではclearFullLayers()という関数名になっているのはバグである。
4. 保留・縮退経路の解消可能性: planが「保留して次ラウンド/リトライに任せる」「fail-closedで何もしない」経路を設計している場合、(a) 保留が解消される条件を仕様文に明記したか、(b) その条件が到達不能になる入力状態が無いかを要素数0・1の最小構成(空集合・単一要素・初回)で列挙したか、(c) テスト指定に最小構成ケースを含めたか。一時的な保留と構造的に永遠に解消しない保留を同じnil/falseに畳むのはplanの失敗である(最小構成で保留が恒久化し無音停止した。incidents #4a)。解消の主体(release/ACK・確認応答を出す側)やその証拠が、封鎖状態を持つプロセスと別のプロセス・別ホスト・別ライフサイクル(シーン/セッション/ドメインリロード)に置かれる設計なら、その主体・証拠が消える入力(プロセス死・ホスト再起動・一時領域の消去・メモリのみの保持)も最小構成として列挙し、封鎖状態の寿命と証拠の寿命を並べて書く(証拠の寿命を問わず恒久封鎖した。#4b)。fail-closed で「この入力では解かない」と決めた分岐には、その入力で代わりに解除へ到達する経路(誰が・どの中継を通って証拠を届けるか)を仕様文に書き、その経路が実際に通るテストを「解かない」テストと対にして指定する。「解かない」側だけをテストで固定すると、代替経路が死んでいても正しさとして保護される(#4c)。
5. 「決定的にする」を根拠にした選択規則: 同点・順序依存の選択を「決定的だから良い」で閉じていないか。決定性は再現性の保証であって選択の正しさの保証ではない。どの候補が選ばれても下流の結果が同型になる論証か、同点fixtureのテスト指定のどちらかを要求する(実例2026-08-18: 同点タイブレークのindex先勝ちが、同期先システムに別の構造を作り巻き戻しを誘発した)。
6. 呼び出し側への責務漏出: 新設サービス/DataStoreのAPIが判定(bool・残数・閾値到達)を返し、その結果を使ったアイテム組み立て・キー正規化・Lookup→Mutationの呼び出し順序が呼び出し側のコード例に現れていないか。Interfaces節に並べたシグネチャを横に見比べ、対になる操作(設置/撤去・取得/適用)の戻り値形状が対称かを確認する。片方が「指示(アイテム列)」で片方が「判定(bool)」なら、判定側を指示型へ書き直すか、その非対称を判断記録に理由付きで残す。計画内で同じ正規化・同じ算術が呼び出し側に2回以上現れたら、それはサービス側へ入る(前例表「判断を内包する新設サービスのAPI形状」の行。裁定: .decisions/2026-08-22-財布システムは指示を返すサービスとしてカプセル化する.md)。
問題を見つけたらその場で修正する。再レビューは不要 — 修正して次に進む。Requirementsの行に対応するタスクが見つからなければ、タスクを追加する。
Simulator Review + 判断記録(ADR)— required, after Self-Review
Self-Review(内容)と spec-architecture-review(構造)を終えたら、Execution Handoff の前に必ず:
- user-simulator スキルを実行する(reviewモード)—
user-simulator/modes/review/protocol.mdに従いFable判事を起動し、予測レポート(元々の想定/適用済み指摘/要裁定/見なかった領域)を受けてCriticalをインライン修正、要裁定はpreanswerを通してAskUserQuestionへ。設計ADR(docs/adr/)とplanの判断記録をcontextに含め、裁定済み事項を蒸し返させない。実行結果の採点を misses.md に記録し、外し(追加指摘/誤検知)は即ハンドオフ発行。 - plan末尾に
## 判断記録(ADR)を置く — 設計セッションのADR(docs/adr/)へのリンク+planning中に新たに生じた判断(タスク分割・機構比較・シミュレーター裁定)を追記する。シミュレーター予測を承認させた裁定は出所「シミュレーター予測→ユーザー承認」と書く。
Execution Handoff
実装は新規セッションでのsubagent-driven-developmentが既定。このセッションで実行方法の選択肢を提示せず、新規セッション用の開始プロンプトを出力して終える(planning済みセッションはコンパクト対象で、コンパクト要約は非監査・何が落ちるか制御できない。監査済み成果物であるplan・ADR・.decisions/だけで開始できる状態を作り、フルコンテキストの新規セッションへ引き継ぐ)。
手順:
-
引き継ぎ完全性チェック: 「planとADRと
.decisions/だけ読んで実装できるか?」に Yes と言えるか確認する。会話の中でしか決まっていない裁定・制約が1つでも残っていれば、planの## 判断記録(ADR)か.decisions/へ書き落としてから次へ進む(新規セッションでは会話コンテキストは完全に消える)。 -
開始プロンプトを出力する: 以下のテンプレートを埋め、ユーザーがそのままコピペできるコードブロックで出力する:
planが完成し`docs/superpowers/plans/<filename>.md`に保存されました。新規セッションを開き、以下を貼り付けて実装を開始してください: ``` subagent-driven-development スキルを使って、以下の実装planを実行してください。 - plan: docs/superpowers/plans/<filename>.md - 作業場所: <ブランチ名>(worktreeの場合はそのパスも記載) - まずplan全文を読み、`## Requirements`・`## Global Constraints`・`## 判断記録(ADR)`を全タスク共通の制約として扱ってください - 進捗管理はsubagent-driven-developmentスキルの規定に従ってください(SDD本体はplanのチェックボックス+進捗台帳、単一subagent実装モードは報告ファイル+進捗台帳が正) - planの最終タスク群(moores-code-reviewによる全ブランチレビュー→pr-createでPR作成・コンフリクト解消まで)は省略不可です。PRが作成されセッションを閉じられる状態になるまで完了扱いにしないでください ```
このセッション内で本体が直接タスクを順次実行することは、ユーザーが明示的に希望した場合のみ行う。自分から選択肢として提示しない(既定は subagent-driven-development の規模ゲートが選ぶモードである)。
追加SKILL:spec-architecture-review
name: spec-architecture-review description: | 設計書(spec)・実装計画(plan)をユーザーレビューやコミットに出す前に、そこに書かれた「配置決定」(どの型・メンバーをどのアセンブリ/層に置くか、どの機構を使うか)を全件抽出し、層責務・既存前例・プロジェクトイディオムと突合して違反を自己修正するレビュースキル。このスキルは「質問にならず設計書へ静かに書き込まれた誤配置」を捕まえる。 Use when:
- 設計書・スペック・実装計画を書き終えて、ユーザーレビュー依頼やコミットに出す直前(毎回必須)
- grill 系スキルで確定した設計を文書化・plan化するフェーズに入る時
- writing-plans 系スキルの「plan self-review」フェーズに入る時
- 設計レビューで「その層に置くのはおかしい」「その機構はプロジェクト標準と違う」という指摘を受けた後の再発防止として
spec-architecture-review — 設計書の配置決定を前例と突合する
なぜこのスキルが必要か
設計書レビューで最も信頼を損なうのは、実装の都合で層責務を破る配置をユーザーに指摘されることである。 「変更箇所が最小になるから既存クラスに足す」「データの出所がマスタだからマスタクラスに置く」という判断は、 書いた瞬間は合理的に見えるが、コードベースの所有権モデルを壊す。 この種の誤りは質問の形を取らないため、書かれた設計書自体を検査する必要がある。
内容の正しさ(プレースホルダ・内部整合・スコープ)は既存の Self-Review(内容検査)が見る。 このスキルが見るのは構造の正しさ: 「どこに置くか」「何の機構を使うか」がこのコードベースの流儀に合っているか。
発火タイミング
設計書・実装計画を「書き終えた」と思った直後、ユーザーに見せる・コミットする前。 plan に対して毎回実行する(設計文書を別途書いた場合はそれにも実行する。文書側で済ませたから plan は不要、とはならない)。
検査スコープ — 何を見て、何を見ないか
このスキルの findings に載せてよいのは構造違反(層責務・前例逸脱・イディオム逸脱)だけである。
見ないもの(findingsに混ぜたら誤り。気づいた場合は findings 外の備考1行に留める):
- 実現可能性・実在性: 参照クラスが実在するか、既存APIで実装が成立するか(実装フェーズとコンパイラの責務)
- 内容の正しさ・網羅性: 要件漏れ、テスト不足、曖昧さ(既存の Self-Review(内容検査)の責務)
- 改善余地: 前例が肯定している形に対する「より良くできる」提案。前例通りの配置は verdict: ok。
違反と断定できるのは規約表・前例と矛盾する場合のみであり、判断が割れる配置(例: どのマスタymlに置くか)は
violation ではなく「新規パターン/判断点」としてユーザー注目点に回す。
ただし前例そのものが「呼び出し側への責務漏出」の形(呼び出し側でのキー正規化・判定後の自前組み立て等)である場合、
「前例準拠」は ok の根拠にならない — 前例は機構でなく役割で選ぶ(AGENTS.md)。その配置は ok に倒さず
「前例自体が漏出形」と注記してユーザー注目点へ回す(実例2026-08-22:
PlaceBlockProtocolのunlock判定で呼び出し側正規化していた前例に倣い、 新設の財布キー正規化も呼び出し側6か所へ置いた計画が「前例適合」で通過した)
レビューの信頼はfalse positiveで最も速く壊れる。迷ったら ok に倒し、注目点として書く。
検査1〜4(配置・機構)は前例が明確なら修正まで行う。検査5〜7(型閉包・重複・ADR矛盾、Phase 2.6)は修正せず問いを出すだけの検査であり、findings とは別枠で扱う。
Phase 1: 配置決定の全件抽出(インベントリ化)
設計書から以下を表に書き出す(頭の中の確認は抽出ではない。書き出さないと漏れる):
| # | 項目(型/メンバー/ファイル) | 配置先アセンブリ・層 | 使用する機構 |
|---|
抽出対象:
- 新規作成・変更するすべてのファイルと、その所属アセンブリ(asmdef 単位)
- 新規の型・public メンバーと、その所属層
- 採用する機構: イベント/通知、永続化、通信、DI 登録、マスタデータアクセス、非同期
既存クラスへのメンバー追加も1行として抽出する。 新規ファイルより既存クラスへの「ちょい足し」の方が誤配置が起きやすい。
Phase 1.5: データフロー地図(既存パイプラインに参加する機能は必須)
対象機能が既存の一方向連鎖(例: 入力→共有モデル書き込み→下流がモデル変化から挙動を導出)に相乗りするなら、配置検査の前に矢印列を1本書き、新規コンポーネントの立ち位置を1語で宣言する:
(駆動元)→(既存の書き手たち)→[共有モデル/状態]→(下流の読み手たち)→(挙動)
- 書き手(共有モデルへ書くだけ)← パイプライン型機能の既定。自由度は「誰が・いつ書くか」だけ
- 読み手(モデル変化を観測して表示・遷移等を足す)
- 交差点(❌)=既存フローに分岐・逆流・並行経路を足すもの: 下流へ制御を返す
bool戻り値/共有モデルを迂回する第2の書き込み経路(下流への直接セッター)/フレーム駆動へのイベント型混入。不可避の理由(既存のどの駅でも表現できない情報・タイミング)を書けないなら書き手/読み手へ畳む
これで前例は「同じ矢印位置の既存コンポーネント」に一意化し(検査2)、交差点の是非は機構選択(検査4)で判定される。根拠: スポイト機能で bool 戻り+各設置システムへの直接セッターを提示し「データフローを一貫(共有選択モデルへ書く一本に)」と全面修正された。矢印列を書けば「PlacementSelection への2人目の書き手」に一意化し両者を交差点として弾けた。
Phase 2: 各行に4つの検査(型・重複・ADR矛盾は Phase 2.6 で別途)
検査1: 層責務(layer ownership)
各行について次の2つを1行ずつ書いて突合する:
- この項目が属するドメインは何か(例: プレイヤーインベントリ)
- 配置先アセンブリの責務は何か(例: Core.Master = マスタデータの生ロード・保持)
判定質問: 「この機能が存在しなかったとしても、この変更はこの層にとって意味を持つか?」 No なら、それはドメイン層に置くべきものである。
共有層(Core.* や複数ドメインから参照される基盤)への追加は挙証責任が逆転する:
「ドメイン非依存であること」を示せない限り追加禁止。ドメインの言葉(プレイヤー、インベントリ、研究…)が
型名・メソッド名に現れる時点でドメイン依存であり、共有層には置けない。
検査2: 前例(precedent)
同カテゴリの既存実装を Grep で探し、配置・命名・機構を比較する:
- 新規 store → 既存の store はどのアセンブリ・どんな形か
- マスタ値の解釈ロジック → 既存はどの層のどんな util か
- 新規イベント → 既存イベントの型・公開方法
- DI 登録・asmdef 参照追加 → 同種の登録・参照の前例
前例は「機構」ではなく「役割」で選ぶ。 「この機構(購読・静的アクセス等)を使っている前例があるか」と探すのは確証バイアス (選んだ機構の前例は大抵1件見つかる)。正しい問いは「同じ役割のコンポーネントは既存でどう駆動・配置されているか」。 役割が違う前例を機構が同じという理由で引用してはならない(例: 受動的な表示オブザーバの購読前例は、 制御に参加するコンポーネントの駆動方式の前例にならない)。
置換・吸収ゲート: 設計が既存コンポーネントを置換・吸収する場合、その置換対象自身の駆動機構が第一の前例である。 機構を変える(駆動→購読、明示呼び出し→イベント等)なら、それは「新規パターン」であり、置換対象の機構との比較付きで ユーザー注目点に載せる。無言の機構変更は禁止。
結果は二択:
- 前例に合わせる(原則こちら。合わせない積極的理由がなければ従う)
- 新規パターンとして設計書に明記(前例が存在しない/割れている場合のみ。理由と一緒に書き、ユーザーレビューの注目点として提示する)
検査3: イディオム(idiom)
プロジェクト規約表(references/ 配下。moorestech なら references/moorestech-layer-map.md を必ず読む)と突合する。
最低限の共通項目:
- イベント・通知の標準機構(このプロジェクトの標準は何か。C# 標準機能で書いていないか)
- 永続化の形式・キー(揮発 ID を保存していないか、マスタ由来値を保存していないか)
- マスタ生成物へのアクセス方法(読み取り専用か、生成クラスへの手出しをしていないか)
- 依存の増やし方(asmdef / パッケージ参照の追加は前例のある形式か)
検査4: 機構選択(leverage-over-replace)
設計が「動作中の既存機構」(状態機械・入力処理・ライフサイクル・既存の同期経路など)に対して 抑止・凍結・迂回・許可リスト制・並行複製のいずれかを導入する場合、それは配置以前の機構選択の分岐点である。 次を必須とする:
- 受動的統合案を必ず併記する: 既存機構を正のまま無傷で動かし続け、新レイヤーは購読・ミラー・ビュー差し替えに徹する案を、 能動介入案と名前付きで並べて head-to-head 比較する(「既存の凍結を温存」「一部だけ許可」も能動介入側に分類する。 片方をコスト過大に描いて棚上げする藁人形比較は比較と認めない)。
- デフォルトは受動的統合。能動介入を選ぶには「既存機構を無傷で活かすと成立しない具体的理由」の明記が必要。 差分の小ささ・実装の速さ・「既存挙動と不変だから安全」は理由にならない。
- 比較の結論と根拠を設計書のアーキテクチャ節に残す(後続レビュアーが分岐を再検証できる形で)。
根拠となった実障害: 動作中の状態機械に許可リスト制の遷移抑止を導入した計画が、全タスク実装完了後に 「既存機構をそのまま活かすべきだった」とユーザー指摘で全面やり直しになった。比較さえ書いていれば設計段階で気づけた。
Phase 2.5: 機能パリティ検査(移行・統合・置換の計画では必須)
計画が触れる機構で現在ユーザーが実際に使える操作(入力キー・画面遷移・常時表示UI・保存等の重要操作)を列挙した 死活表(操作 → 計画後も生きるか → 根拠1行)を設計書に含める。列挙は「触るコードの操作」でなく 「同じ機構にぶら下がる全操作」を対象にする(自分が変えない操作が巻き添えで死ぬのが典型事故)。
- 1つでも死ぬ・退化する操作がある場合、それを「既知の制限」として計画内で確定するのは禁止。 それは制限ではなく裁定事項であり、実装開始前にユーザーへ選択肢付きの質問として提示し、裁定を得るまで当該部分の実装に進まない。
- 「新規パターン」「レビュー注目点」として設計書に書くだけで実装を開始するのも同じ違反(フラグ記載は裁定の代替にならない)。
根拠となった実障害: 「モード切替キーが効かなくなる」「常時HUDが消える」を既知の制限として計画内で独断確定した結果、 実装完了後にユーザー指摘で全面やり直しになった。死活表と裁定ゲートがあれば1問の質問で防げた。
Phase 2.6: 型閉包・重複・ADR矛盾(検査5〜7・fresh-context subagent・毎回必須)
配置が正しくても、型の形が閉じていなければ実装レビューで差し戻される。採用済み critical のうち最大群は層配置の誤りではなく「不在や数値を合図に使う」「3状態を bool に畳む」「前提を確かめる仕組みが無い」の型未閉包で、その過半は plan 本文に既に書かれていた(incidents #T1)。
実行形態: 本体ではなく fresh-context の subagent(opus)に委譲する。本体は plan を書いた当人で、自分が書いた形を「そう書いた理由」ごと読んでしまう。派遣プロンプトに渡すのは次の4つだけ:
- plan のパス
references/type-closure-patterns.md(検査5〜7の発火条件表)とreferences/moorestech-layer-map.md- plan が参照する ADR のパス(
docs/adr/) - 本体が plan 作成中に読んだ既存ファイルの一覧(Files 節の Modify 対象+前例として引用したファイル)— 検査6の Grep 起点
検査範囲: plan の構造化6節(Files / Interfaces / Produces・Consumes / 配置表 / コードブロック / 判断記録・やらないこと)のみ。散文節は読ませない。発火条件は表の字面で当てる。表に無い形を「悪そうだから」で足すのは禁止(迷ったら ok)。
出力: 1発火=1行「〈検査番号・パターン〉[強|弱] / plan の行 / 表の問い」。表の「出力の畳み方」に従い、同じ行の複数箇所は1件にまとめ、テストコードは 5-D/5-F/検査6 の対象外、強弱の印を付ける。subagent は plan を書き換えない。本体は 強を AskUserQuestion の1問ずつ(選択肢: 表の問いの Yes/このままでよい)、弱は plan 全体で1問(箇所を列挙し「拾うものはあるか」)にしてユーザーへ出し、裁定を ## 判断記録(ADR) に書く。「このままでよい」も裁定として残す。
第3バケツ: 検査6の最終行(Produces の新設判定と同役割の既存実装が plan 外のファイルに見つかる)だけは plan の問いにせず、レビュー依頼文の 「本PR外のリファクタ提案」節に1行ずつ列挙して人間に渡す。plan のタスクには決して足さない(範囲の膨張は別の失敗)。
射程外: 「plan は正しかったが実装が逸脱した」ケースはここでは拾えない。それは SDD の task-reviewer が plan の Interfaces と実装の型差分を見る仕事である。
Phase 3: 修正と記録
- 違反は質問せず修正する。 前例が明確なら、それに合わせるのはユーザーの判断を要しない
- 修正した設計書に**「レイヤリング制約」または「配置と前例」セクション**を残し、主要な配置決定に前例(ファイルパス)を引用する。これが次のレビュアー(人間・AI とも)の検証コストを下げる
- 前例のない「新規パターン」だけを、ユーザーレビュー依頼文で注目点として列挙する
- Phase 2.6 の第3バケツ(本PR外のリファクタ提案)は、レビュー依頼文の別節に「既存側ファイル/新設側/同役割と判断した根拠1行」で列挙する。着手可否は人間が決める
- 検査で層マップ・規約表に載っていない規約違反を指摘されたら、
references/の規約表に追記する(このスキル自体を成長させる)
Red Flags — この思考が出たら検査に戻る
| 思考 | 現実 |
|---|---|
| 「変更が最小だから既存クラスに足す」 | 差分最小は層違反の正当化にならない。診断: 判定質問(Phase 2 検査1)を通せ |
| 「データの出所がマスタだからマスタクラスへ」 | データの出所と解釈ロジックの所有者は別物。解釈はドメイン層が持つ |
| 「新機能だから新しい制御フロー(bool戻り・専用セッター・イベント)を足す」 | 既存パイプライン参加機能の実体は「書き手が1人増える」だけ。Phase 1.5 で矢印列を書き、交差点を足していないか確認せよ。新設サービスなら bool は「指示を返す形」へ(前例表「判断を内包する新設サービスのAPI形状」) |
| 「C# 標準の event/Action で十分」 | 機構選定の基準は十分性ではなく統一性。プロジェクト標準に合わせる |
| 「planに書くほどの詳細ではない」 | 配置とイディオムは設計の一部。書かなければ実装時に都合で決まる |
| 「後で直せる」 | 設計書に書いた配置はそのまま実装・レビューされ、手戻りが最大化する |
| 「既存機構を凍結/抑止/許可リストで黙らせるのが手っ取り早い」 | それは機構選択の分岐点。検査4で受動的統合案(無傷で動かし購読・ミラー)と名前付き比較せよ |
| 「動いている機能が死ぬのは既知の制限と書けばよい」 | 動作中機能の喪失は制限でなく裁定事項。Phase 2.5 の死活表に載せ、実装前に選択肢付きで質問する |
| 「セルフレビューはもうやった」 | 既存 self-review は内容検査。構造検査(このスキル)は別物で、両方やる |
| 「既存イベントを購読すれば呼び出し側を触らずに済む」 | 制御に参加するコンポーネントは呼び出し側(ステート等)から駆動されるのが原則。購読で済ませてよいのは受動的な表示オブザーバだけ |
| 「発火順・タイミングの都合はこう回避する」 | 選んだ機構のせいで回避策(発火順の妥協、二重管理等)が必要になったら、それは機構選定ミスのサイン。回避策を書く前に駆動方向を反転した案と比較する |
| 「新規プロトコル・イベントは作らず既存応答から導出する」 | サーバー可変状態の同期は3点セット(イベント+初期データ+購読)が標準。別ドメイン応答からの推測合成(Applier)は導出ではない。イベントを作らない決定は新規パターンとして裁定に出す |
| 「既存JSONを壊さないためoptional+デフォルト値にする」 | 後方互換は考慮不要(AGENTS.md)。必須化+全JSON一括更新が正規手順。フォールバックの散布はレビューで全排除される |
| 「null なら未設定、-1 なら無効、で十分」 | 不在・数値を合図にした型は実装レビューで最も多く差し戻される群。Phase 2.6 検査5(A・B)の問いに答えてから進む |
| 「この前提は成り立つはずだから検査は要らない」 | 括弧書きの前提は転写されるだけで強制されない。検査5(E): 型・マスタ検証・テストのどれで閉じるかを決める |
| 「同じ判定が既にあるが今回の範囲外」 | それは第3バケツ(本PR外のリファクタ提案)。黙って新設せず人間に1行で渡す |
アンチパターン実例
上の検査項目はいずれも実際の差し戻しから生まれた。事案の経緯は references/incidents.md(#S1〜#S5)。検査項目を足すときは事案を incidents.md に書き、本文には検査条件とWHY一句だけを残す。