プロジェクト設計の再起動
既にコードがあるプロジェクトを走査し、「プロジェクト定義」を作る Skill。
- 入力: 既存のリポジトリ
- 出力:
docs/project-definition.md。project-design-openingが作るものと同じ書式の、固定書式のプロジェクト定義 - 対象: 種類は問わない(Web サービス、CLI、ライブラリ、デスクトップアプリ、モバイルアプリ、バッチ処理など)。コードがまだ無い新規プロジェクトは
project-design-openingの対象 - 扱わないこと: コードの品質評価、リファクタリングや構成変更の提案、詳細な機能一覧や設計の復元、画面・API・DB スキーマの文書化
この Skill の位置づけ
プロジェクト定義への入口は2つある。どちらも同じ docs/project-definition.md を出し、同じ次の段階につながる。
曖昧なアイデア(新規) → project-design-opening ─┐
├→ docs/project-definition.md → project-design-harness → 詳細設計 → 開発
既存のリポジトリ → project-design-reboot ──┘
Agent に開発を任せるには、「何を扱うシステムなのか」「どこに境界があるのか」「外の世界にどんな作用を及ぼすのか」が決まっている必要がある。権限も、検証の方法も、承認が要る操作も、そこから導かれる。 新規プロジェクトでは、それを対話で決める。既存プロジェクトでは、その大半が既にコードの中に答えとして存在する。だからこの Skill は、聞く前に読む。
終了条件は project-design-opening と同じ。次の Skill が、プロジェクトの基本情報をユーザーに聞き直さずに動ける状態になること。具体的には、入力契約 A〜H の全項目が状態を持つこと。
5つの原則
1. 先に読む。コードから分からないことだけ聞く
lockfile を見れば分かるパッケージマネージャを、ユーザーに聞いてはいけない。技術・リポジトリ構成・システム境界は、人の記憶よりコードの方が正確である。 聞くのは、コードに書かれていないことだけ。何をやらないと決めているのか。どんな制約があるのか。リポジトリの外で何をしているのか。 走査を先に終えてから対話に入る。読みながら小出しに聞くと、後で読めば分かったことまで聞いてしまう。
2. 読み取ったことは、確認されるまで仮定である
走査の結果は、根拠つきの推測であって事実ではない。依存に入っているが使われていないライブラリもあれば、移行の途中で古い設定が残っていることもある。
読み取った内容は一覧にして見せ、ユーザーに確認してもらう。確認が取れて初めて assumed と書ける。確認を取っていない推測を、成果物に書かない。次の Skill が、その上に権限と安全策を組み立てるからだ。
3. 「見つからなかった」は、「無い」ではない
この Skill で最も危険な誤りは、区分 D(リスク)で、検出できなかったものを none と書くことである。
依存に決済の SDK があれば、課金があると言える。しかし何も見つからなくても、外部作用が無いとは言えない。管理画面からの手動デプロイも、本番 DB への手作業の接続も、リポジトリに痕跡を残さない。
none と書いてよいのは、ユーザーに聞いて、無いと確認が取れたときだけ。誤った none は、次の Skill が安全策を省く方向に倒れる。
4. あるがままを書く
成果物は、このプロジェクトの現状の定義であって、あるべき姿の提案ではない。「この構成は分けた方がよい」「このライブラリは古い」といった評価や提案を、成果物にも対話にも持ち込まない。 ユーザーが今後の変更予定を話したら(「来月 DB を移行する」など)、区分 H に持ち越しメモとして残す。定義に書くのは、今のコードの姿である。
5. 秘密を文脈に入れない
.env のような、実際の値が入っているファイルの中身を読まない。見るのは、そのファイルが存在することと、.env.example などの雛形に書かれたキーの名前だけ。
キーの名前(STRIPE_SECRET_KEY、DATABASE_URL)は、外部サービスと秘密情報の有無を知るのに十分で、値は要らない。読んだ値は文脈に残り、どこかに書き出されるおそれがある。
入力契約 A〜H
成果物は次の8区分を持つ。各区分の項目と「埋まったと言える基準」は references/input-contract.md にある。Step 1 に入る前に読む。
| 区分 | 内容 | この Skill での埋め方 |
|---|---|---|
| A 目的とスコープ | 目的/やること/やらないこと/制約 | 目的とやることは README などから読む。やらないことと制約は聞く |
| B システム境界 | 利用者との接点/処理/データの保存先/外部とのやりとり/利用者の識別(認証)/配布・実行場所、および相互の関係 | 読む |
| C 技術 | 言語/ランタイム/パッケージマネージャ/主要フレームワーク/DB 種別/デプロイ先種別 | 読む |
| D リスク | 外部作用/不可逆・機微な操作/秘密情報・個人情報 | 検出できたものは読む。検出できなかったものは聞く |
| E 環境 | 開発環境(OS・コンテナ利用)/実行環境の段階(local・staging・本番)/リポジトリのホスティング/CI の有無 | 読む。リポジトリに現れない部分(本番の有無など)は聞く |
| F リポジトリ構成 | 単一か分離か/最上位の配置/新規か既存か/(あれば)設計文書の場所 | 読む |
| G 運用前提 | ソロかチームか/試作か本番品質か | 手がかりを読み、確かめる |
| H 未決・持ち越し | 未決事項/後続への持ち越しメモ | 対話と走査で出たものを残す |
各項目は次のいずれかの状態を持つ。状態のキーは、成果物を何語で書いても変えない。
| 状態 | 意味 |
|---|---|
decided |
ユーザーが自分の言葉で述べた、訂正した、または複数の候補から選んだ |
assumed |
この Skill がコードから読み取った内容を、ユーザーがそのまま認めた |
none |
該当するものがない、とユーザーが確認した。または、走査で無いことが明らかで、確認が取れた |
deferred |
ここでは決めず、後続に持ち越す |
区分 C の6項目と区分 D の3項目は、deferred にできない。次の Skill が、権限と安全策を具体的に書くための材料だからだ。
状態の付け方で迷う場面の決まり。
- 手がかりが食い違っていて、ユーザーがどちらかを選んだ →
decided - 手がかりを示して確かめ、ユーザーが「そのとおり」と認めた →
assumed。ユーザーが自分の言葉で言い直した、付け足した →decided - 1行の中に、読み取った部分とユーザーが述べた部分が混ざる → 行を分ける。分けられなければ
decided - 項目の一部だけが「無い」場合は、
noneの行を作らない。noneは、その項目の全体が無いときだけに使う。「手動のデプロイはしていない」は、noneではなく、そう書いた行をdecidedで足す。外部作用の全体が無いと誤読されるのを防ぐためだ
ワークフロー
Step 0: 前提の点検
始める前に、作業ディレクトリの状態を見る。見るのは3点。ソースコードがあるか(README や LICENSE、.gitignore、docs/ だけならコードなしと見なす)。docs/project-definition.md があるか。ハーネスがあるか(docs/agent-architecture.md があり、そこに一覧された生成ファイルが実際に存在するか)。
| コード | 定義 | ハーネス | 振る舞い |
|---|---|---|---|
| なし | — | — | この Skill の対象ではない。project-design-opening を案内して終了する |
| あり | なし | — | そのまま Step 1 へ |
| あり | あり | なし | 既存の定義を置き換えることを伝え、Step 1 から進める。既存の定義は、走査の結果と突き合わせる材料として読んでよい |
| あり | あり | あり | 何も変更せず、通常の設計作業へ案内して終了する |
ハーネスが既にあるプロジェクトでは、定義の変更は、そのプロジェクトの通常の設計作業として docs/project-definition.md を直接更新してもらう。区分 C(技術)・D(リスク)・E(環境)が変わる場合は project-design-harness の再実行が必要になることも伝える。
Step 1: 走査する
references/scan.md の手順で、リポジトリを読む。このステップでは、ユーザーに何も聞かない。
- 区分 B の捉え方と図の描き方は references/boundaries.md、区分 D の検出の手がかりは references/scan.md の該当の節を、走査の前に読む
- 読む順は、構成ファイルと依存の定義 → CI とデプロイの設定 → 環境変数の雛形 → README と既存の文書 → エントリポイントと最上位の配置。コード全体を読み込まない
- 読み取った項目には、必ず根拠を控える。根拠は、ファイル、git の情報(リモート、著者の数、タグ)、いま動いている環境のいずれか。根拠を示せない推測は、走査の結果に入れない
- 依存にあるが使われているか怪しい外部サービスの SDK は、その名前を import している行があるかを検索して確かめる。コードを読む必要はない。A〜H のどの項目にも関係しない補助のライブラリは、使われていてもいなくても、走査の対象にしない
- 区分 D は、検出できた「ある」だけを控える。検出できなかった項目は「未検出」として控え、
noneにしない - 秘密の値が入ったファイルは、中身を読まない
Step 2: 走査の結果を、まとめて確認してもらう
読み取った内容のうち、区分 B・C・E・F(構造についての事実)を、区分ごとの一覧にして見せる。1行につき、項目、読み取った内容、根拠。ユーザーには、違うものだけ直してもらう。 区分 A・D・G は、ここでは見せない。コードから分からないことと一緒に確かめる必要があるので、Step 3 で、それぞれの質問の冒頭に見せる。
- 一覧は、読める長さにする。20〜30 行。コードの細部を並べない
- 確信の弱い項目(依存にあるが使われている形跡が薄い、雛形のキーの名前しか手がかりが無い、など)は、その旨を添えて見せる。確信があるふりをしない
- 弱い項目は、沈黙を確認と見なさない。「違うものだけ直してください」で通してよいのは、根拠の強い項目だけ。弱い項目は、まとめて「この3点は合っていますか」と明示的に可否を聞く。確認が取れなければ表には書かず、区分 H に未確認として残す
- 確認が取れた項目が
assumedになる。Step 3 で見せて確かめた区分 A・D・G の項目も同じ
手がかり同士が食い違っているとき(lockfile が2種類ある、手元の設定と本番の設定でバージョンが違う、など)。片方に強い根拠が揃っているなら(packageManager の欄・CI・Dockerfile がすべて pnpm を指している、など)、そちらを読み取った値として見せ、食い違う手がかりが残っていることを添える。これだけのために質問を増やさない。
強さが同じくらいなら、片方を選ばずに両方を根拠つきで見せ、どちらが正しいかを確かめる。どちらの場合も、食い違いがあった事実は区分 H に1行残す。
走査の結果とユーザーの答えが食い違ったとき。ユーザーの答えが、コードから読み取れることと違っていたら(lockfile は pnpm なのに「npm を使っている」と言われた、など)、黙って上書きも無視もしない。
根拠のファイルを示して、どちらが正しいかを確かめる。ユーザーの答えを採用し、状態は decided にする。該当の行には、採用した値と一言の補足だけを書き、経緯は区分 H に1行残す。
移行の途中のように、コードより意図の方が正しい場面がある。記録しておけば、後で権限の設定が実態と合わないときの手がかりになる。
Step 3: コードから分からないことを聞く
references/input-contract.md と照らし、まだ状態を持たない項目を洗い出して聞く。質問は 5 回前後に収める。目安は、区分 D に 3 回、区分 A に 1 回、区分 G と区分 E の残りをまとめて 1 回。Step 2 の食い違いの確認は、これとは別に数える。
聞き方の決まり。
- 選択式の質問ツールが使える環境ではそれを使い、無ければ平文で聞く
- 一度に聞くのは1つの話題。ただし、関連する小さな項目(ソロかチームか、試作か本番か、staging の有無)は、1回にまとめてよい。質問の数を抑えるためだ
- 選択肢を出すときは、選んだ結果どうなるかを添える。推奨があれば先頭に置き、推奨であることを示す
- 「分からない」という答えは正当な答えとして扱う。区分 C・D 以外なら
deferredにできる
区分 D(リスク) が、このステップの中心である。走査で検出できたものを先に見せ、そのうえで、検出できなかった項目を具体的に聞く。聞き方と例は references/risk.md。特に、リポジトリに痕跡が残らないものを聞く。
- コードや CI の外で行っている、外へ影響が出る操作はあるか(管理画面からの手動デプロイ、手作業でのリリース、外部サービスの管理画面での設定変更)
- 本番のデータに、開発の環境から触れられるか(本番 DB への接続情報が手元にある、など)
- 検出した外部サービスについて、開発中はテスト用の接続先を使っているか
3項目それぞれについて、「ある」か none かを確定させる。検出できなかったことだけを理由に none と書かない。
区分 D の行には、その操作を実行する道具とコマンドの名前を書く。「本番へのデプロイ」ではなく「Fly.io への本番デプロイ(flyctl deploy)」、「本番 DB への接続」ではなく「本番 DB への手作業での接続(psql)」。
次の Skill は、定義に名前が出ている道具についてだけ、承認や禁止の規則を作る。名前が落ちると、その操作を止める規則は作られない。
危険なコマンドを包んだ scripts があれば(db:reset が prisma migrate reset --force を呼ぶ、など)、scripts の名前と、中で呼ばれるコマンドの両方を書く。包まれた形は、コマンドの文字列からは中身が見えないので、名前で規則にするしかない。
3つ目の問い(開発中の接続先)の答えは、外部サービスごとに、区分 D の「外部作用」の行として書く。「開発中の Stripe は、テスト用のキー」「開発中の Resend は、本物のキー。開発環境からも実際に送信される」。後者のような事実は、開発中の事故に直結するので、必ず残す。
区分 A の「やらないこと」と「制約」は、コードにはほとんど書かれていない。目的と「やること」を走査の結果から示したうえで、聞く。 区分 G は、手がかり(コミットの著者の数、バージョン、本番向けの設定の有無)を示して、確かめる。 区分 E のうち、リポジトリから読めなかったもの(staging や本番の有無など)を聞く。
対話の中でユーザーが、今後の変更予定や、詳細な機能の話を始めたら、遮らずに聞き、要点を区分 H に deferred として残す。追加の質問で掘り下げない。
Step 4: 書き出す
全項目が状態を持ったら、docs/project-definition.md を書く。docs/ が無ければ作る。既存プロジェクトが設計文書を別の場所(doc/、design/ など)に置いていても、この定義は docs/ に書く。次の Skill が、その前提で動くためだ。
- 書式は assets/project-definition.template.md に従う。記入例は assets/example.md
- 走査で読み取った行は、内容の末尾に根拠を書く。「pnpm(根拠:
pnpm-lock.yaml)」の形。列は足さない - 既存の設計文書のフォルダが
docs/以外にあれば、区分 F に「設計文書の場所」の行を足す。次の Skill が、その場所を設計の対話役が書ける範囲に含める - 区分 F の「新規か既存か」は「既存」。「最上位の配置」には、この Skill が新しく作る
docs/を書かない。走査の時点であった配置を書く - 既存の検証系のコマンド(test、lint、typecheck など)を見つけていたら、区分 H に持ち越しメモとして残す。区分 C の項目は増やさない
- 本文はユーザーが会話している言語で書く。区分の記号(A〜H)、状態のキー、フロントマターのキーは言語によらず固定
- フロントマターの
statusはcomplete。ユーザーが途中で切り上げた場合はdraftにし、状態の付いていない項目を区分 H に列挙する。次の Skill はdraftの定義では動かない
Step 5: 次の段階を案内する
次は project-design-harness で、この定義を入力に Agent とハーネスを作る段階であることを伝える(Claude Code 向け)。
既存の .claude/ や CLAUDE.md がある場合は、次の Skill が書く前に計画を見せ、人が書いたものを保つことも伝える。この Skill の中で、Agent の設計やハーネスの生成を始めない。
出力フォーマットの決まり
project-design-opening と同じ書式を守る。次の Skill は、どちらの入口から来た定義かを区別しない。
- 1ファイルの Markdown。先頭の YAML フロントマターに
schema: project-definition/1、status、updatedを持つ - 見出しは
## A.〜## H.の固定順。区分を省略しない - A〜G は「項目/内容/状態」の3列の表。1行に1項目。内容が複数ある項目は行を分ける
- 区分 B には表に加えて、境界同士の関係を示すテキストの図を置く
- ツールチェーンが複数ある場合は、区分 C の表を構成要素ごとに分ける
- 該当しない項目は空欄にせず、内容を「なし」、状態を
noneにする - 区分 H は箇条書き。各行の先頭に
[deferred]を付ける。何も無ければ「なし」と書く
避けるパターン
| パターン | 避ける理由 |
|---|---|
| 走査する前に質問を始める | 読めば分かることを聞くことになる。ユーザーは、コードを見れば分かるはずだと感じる |
検出できなかったリスクを none と書く |
手動の操作はリポジトリに痕跡を残さない。誤った none は、次の Skill が安全策を省く方向に倒れる |
| 読み取った内容を、確認せずに書き出す | 使われていない依存、古い設定、移行の途中を、事実として固定してしまう |
.env の中身を読む |
秘密の値が文脈に入り、どこかに書き出されるおそれがある。キーの名前で足りる |
| コード全体を読み込む | 文脈を使い果たし、肝心の構成ファイルが埋もれる。境界を知るのに、実装の中身は要らない |
| 食い違いを、黙ってどちらかに寄せる | コードが古いのか、ユーザーの記憶違いなのかは、確かめないと分からない。根拠を見せて聞く |
| 構成の良し悪しを評価する、直し方を提案する | この Skill が書くのは現状の定義。評価と提案は、頼まれていない |
| 依存の一覧や、ファイルの一覧を成果物に写す | 定義は境界の要約であって、目録ではない。詳細はコードにある |
| 定義を、既存の設計文書フォルダに合わせて別の場所に書く | 次の Skill は docs/project-definition.md を前提にしている。既存の場所は、区分 F に記録して渡す |
| Agent の分割案を成果物に書く | システムの境界と Agent の境界は別物。分割は次の Skill が別の観点から決める |