Next.js v16でAI駆動開発を実践!モダンフロントエンド開発におけるSDD・TDD・Codex・ハーネスエンジニアリング


 

こんにちは。Tomoyuki(@tomoyuki65)です。

2026年以降のシステム開発では、コードはAIにかかせるAI駆動開発が主流になるのは避けられません。

特にフロントエンド開発については、バックエンド開発に比べて責任範囲が狭く、AIが生成したコードをそのまま採用しても致命的な障害に繋がりにくいため、モダンなフロントエンド開発はどんどんAI駆動開発に置き換わっていきそうです。

そんな私も直近ではRuby on RailsによるAI駆動開発を試してAIの凄さを体感し、次はフロントエンド開発にも適用していくべきと思い、Next.jsでも試してみることにしました。

ということでこの記事では、私が試したNext.jsによるAI駆動開発の実践方法についてご紹介します。

 

関連記事

Ruby on Railsで始めるAI駆動開発×TDD実践|Codexとハーネスエンジニアリングで作るDDDモジュラーモノリス

2026年4月24日

 



目次

Next.js v16でAI駆動開発を実践!モダンフロントエンド開発におけるSDD・TDD・Codex・ハーネスエンジニアリング

まず今回はmacOS(Apple silicon)のPCを使い、パッケージ管理に「Homebrew」、コード管理に「Git」や「GitHub」、AIツールはOpenAIの「Codex」を利用する前提で進めます。

以降の内容を参考にしたい場合は、事前にこれらを利用できるように準備して下さい。

※GitHub CLIとして「gh」コマンドも準備が必要です。これはHomebrewでインストールできます。

 

関連記事

・OpenAI Codex CLI / Codexアプリの使い方【ChatGPT時代のAI開発ツール入門】

 

Node.jsの準備

まずフロントエンド開発ではNode.jsを使う必要があり、その際には何らかのバージョン管理ツールを利用するのがおすすめです。

私はvoltaを気に入っているので、今回はその例でご紹介しますが、voltaをインストールしたい場合は以下のcurlコマンドを実行すると可能です。

$ curl https://get.volta.sh | bash

 

インストール後、以下のコマンドでパスが通っているか確認して下さい。

$ volta -v

 

次に以下のコマンドを実行し、nodeをインストールします。

$ volta install node@24.15.0

※ここでは2026年5月時点でLTS版のバージョン「24.15.0」を使います。尚、チーム開発などではnodeのバージョンは固定推薦です。

 

インストール後、以下のコマンドでパスが通っているか確認して下さい。

$ node -v

 

パッケージマネージャー「pnpm」の準備

次にnodeを使う際はパッケージマネージャーとして付属のnpmを使うことが多いですが、最近だとCI(継続的インテグレーション)でキャッシュを利用することを考慮し、pnpmの利用が増えているため、今回はそれを試します。

そんなpnpmもバージョン固定を想定し、corepackを利用する方法で導入するため、まずは以下のコマンドを実行してcorepackをインストールします。

$ volta install corepack

 

インストール後、以下のコマンドでパスが通っているか確認して下さい。

$ corepack -v

 

次に以下のコマンドを実行し、corepackを有効化します。

$ corepack enable

 

次に以下のコマンドを実行します。

$ pnpm -v

 

コマンドを実行するとpnpmをインストールするか聞かれるので、「y」を入力してインストールを進めます。

インストール完了後、再度以下のコマンドを実行し、パスが通っていればOKです。

$ pnpm -v

※今回の最新バージョンは「10.33.2」でした。

 

Next.jsの新規プロジェクト作成

次に以下のコマンドを実行し、Next.jsの新規プロジェクトを作成します。

$ mkdir next16-aidd && cd next16-aidd
$ pnpm create next-app@latest .

※今回は2026年5月時点で最新のバージョン16を利用しています。

 

コマンドを実行後、「No, customize settings」を選択し、以下の選択肢で作成します。

 

  •  TypeScript を使用しますか?:「Yes」
  •  どのリンターを使用しますか?:「Biome」
  •  React Compiler を使用しますか?:「No」
  •  Tailwind CSS を使用しますか?:「Yes」
  •  コードを src/ ディレクトリ内に配置しますか?:「Yes」
  •  App Router を使用しますか?(推奨):「Yes」
  •  インポートエイリアス(デフォルトでは @/*)をカスタマイズしますか?:「No」
  •  最新の Next.js コードを書くためのガイドとして AGENTS.md を含めますか?:「No」

※フォーマッターやlintにはモダンな「Biome」を試します。

 

実行後、以下のようにNext.jsのプロジェクトが作成されればOKです。

 

次にローカルサーバーの起動を試すには以下のコマンドを実行します。

$ pnpm dev

 

サーバー起動後、ブラウザで「http://localhost:3000」にアクセスし、以下のように表示されればOKです。

 

起動したサーバーを止めたい場合は、ターミナルがアクティブの状態でショートカットキー「control + c」を使うと止めれます。

 

nodeとpnpmのバージョン固定

次にnodeとpnpmのバージョン固定を行います。まずは以下のコマンドを実行し、ファイル「.npmrc」を作成します。

$ touch .npmrc

 

次に作成したファイル「.npmrc」は以下のように記述します。

engine-strict=true

 

次にファイル「package.json」に対して以下のように「engines」を追加します。

{
  "name": "next16-aidd",
  "version": "0.1.0",
  "private": true,
  "engines": {
    "node": "24.15.0",
    "pnpm": "10.33.2"
  },
  "scripts": {

・・・

※pnpmのバージョンはインストール時に「10.33.2」だったのでこれで固定しています。必要に応じて修正して下さい。

 

次に以下のコマンドを実行し、corepackでpnpmを固定できるようにします。

$ corepack use pnpm@10.33.2

※pnpmのバージョンはインストール時に「10.33.2」だったのでこれで固定しています。必要に応じて修正して下さい。

 

コマンド実行後、「package.json」に「packageManager」が追加されればOKです。

 

biomeのコマンド修正

次にファイル「package.json」にあるbiomeのコマンドを以下のように修正します。

・・・

  "scripts": {
    
    ・・・

    "lint": "biome lint",
    "format": "biome format --write",
    "check": "biome check --write",
    
    ・・・
  },

・・・

※基本的に「check」(フォーマット修正、import整理、lintチェック)を実行するのがおすすめです。

 

pnpmのストアをgit管理対象外にする

次にpnpmを利用した際に作成されるストア(共有キャッシュ)ファイルをgit管理の対象から外すため、「.gitignore」に以下を追加します。

・・・

# pnpm
.pnpm-store

 

Storybookの導入

次にフロントエンド開発ではSDD(Storybook Driven Development)で行うのが最適なので、以下のコマンドを実行してStorybookを導入します。

$ pnpm create storybook@latest

 

実行後、オンボーディングの有無が聞かれるので、どちらかを選択します。

  •  Yes(はい): Help me with onboarding(オンボーディングを手伝ってください)
  •  No(いいえ): Skip onboarding & don’t ask again(オンボーディングをスキップして、今後表示しないでください)

 

次に「Do you want to install Playwright with Chromium now?(PlaywrightをChromiumと一緒にインストールしますか?)」も聞かれるので、「Yes」を選択します。

※Playwright(プレイライト)は、Microsoft製のWebブラウザ操作を自動化するOSSのフレームワークです。Chromium、Firefox、WebKit(Safari)の3つの主要エンジンを1つのAPIで操作でき、高速かつ安定したE2Eテストやスクレイピング、業務自動化に利用されています。

 

全て完了後、ブラウザで「http://localhost:6006」が自動で開き、Storybookの画面が表示されればOKです。

※Storybookのサーバーも止めたい場合はターミナルがアクティブの状態でショートカットキー「control + c」を使います。

 

次にStorybookでTailwindCSSを有効化するのと、viewportの設定も追加しておくため、ファイル「.storybook/preview.ts」を以下のように修正します。

import type { Preview } from '@storybook/nextjs-vite'
// TailwindCSSの読み込み
import "@/app/globals.css";
// viewportをインポート
import { INITIAL_VIEWPORTS, MINIMAL_VIEWPORTS } from "storybook/viewport";

const preview: Preview = {
  parameters: {
    // viewportの設定追加
    viewport: {
      options: {
        ...INITIAL_VIEWPORTS,
        ...MINIMAL_VIEWPORTS,
      },
    },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },

    a11y: {
      // 'todo' - show a11y violations in the test UI only
      // 'error' - fail CI on a11y violations
      // 'off' - skip a11y checks entirely
      test: 'todo'
    }
  },
};

export default preview;

 

次にNext.jsで合わせて導入してあるBiome(format・lintツール)のチェックで、Storybookのインストール時に自動で追加されたファイルをチェックの対象から外すため、ファイル「biome.json」の「files」に「”!src/stories”」を追加します。

{

・・・

  "files": {
    "ignoreUnknown": true,
    "includes": [
      "**",
      "!node_modules",
      "!.next",
      "!dist",
      "!build",
      "!src/stories"
    ]
  },

・・・

 

vitestの設定

Storybookを導入すると、合わせてviteやvitestも導入され、特にvitestはフロントエンド開発のunitテストやintegrationテストで利用します。

そのままだと必要なライブラリが足りないため、以下のコマンドを実行して追加のライブラリをインストールします。

$ pnpm add -D jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event @vitejs/plugin-react msw msw-storybook-addon @playwright/test

 

次に一部のライブラリは導入に承認が必要になるため、以下のコマンドを実行します。

$ pnpm approve-builds

 

実行後、 Choose which packages to build(ビルドするパッケージを選択してください)が聞かれるので、そのままEnterを押して実行すると、承認完了です。

※この承認作業については、よくわからないライブラリは入れないようにするためのもの(セキュリティ対策)なので、その点は理解して承認して下さい。

 

次に以下のコマンドを実行し、vitest用のセットアップファイルを追加します。

$ touch vitest.setup.ts

 

次に作成したファイル「vitest.setup.ts」を以下のように記述します。

import "@testing-library/jest-dom";

 

次にファイル「vitest.config.ts」を以下のように修正し、ユニットテスト用の設定を追加します。

・・・

// vitest用の設定追加
import react from "@vitejs/plugin-react";

const dirname =
  typeof __dirname !== 'undefined'
  ? __dirname
  : path.dirname(fileURLToPath(import.meta.url));

// エイリアス設定追加
const alias = [
  {
    find: /^@\//,
    replacement: `${path.join(dirname, "src")}/`,
  },
  {
    find: "@",
    replacement: path.join(dirname, "src"),
  },
] as const;

// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon
export default defineConfig({
  // エイリアス設定追加
  resolve: {
    alias,
  },
  test: {
    projects: [
      // ユニットテスト用(integration含む)
      {
        plugins: [react()],
        resolve: {
          alias,
        },
        test: {
          name: "unit",
          environment: "jsdom",
          globals: true,
          setupFiles: ["./vitest.setup.ts"],
          include: [
            "src/**/*.{test,spec}.{ts,tsx}",
            "tests/integration/**/*.{test,spec}.{ts,tsx}",
          ],
        },
      },
      // Storybook用
      {

・・・

 

次にファイル「package.json」にテスト用コマンドを追加します。

・・・

  "scripts": {
    
    ・・・

    "build-storybook": "storybook build", // 末尾に追加するならカンマ追加して下さい
    "test": "vitest run --project unit --reporter=verbose",
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui"
  },

・・・

※playwright用のコマンドも合わせて追加してます。

 

mswの設定

次にmsw(APIのモック用サーバーライブラリ)の設定を行います。

まずは以下のコマンドを実行し、各種ファイルを追加します。

$ mkdir -p src/lib/msw/handlers && touch src/lib/msw/handlers/sample.ts
$ mkdir -p src/lib/msw/setup && touch src/lib/msw/setup/server.ts

 

次に作成したファイルをそれぞれ以下のように記述します。

・「src/lib/msw/handlers/sample.ts」

import { HttpResponse, http, type RequestHandler } from "msw";

const helloHandler = http.get("http://localhost:3000/hello", () => {
  return HttpResponse.json({
    message: "Hello World !!",
  });
});

export const sampleHandlers: RequestHandler[] = [helloHandler];

※これはモック化用のハンドラーファイルのサンプルです。

 

・「src/lib/msw/setup/server.ts」

import { setupServer } from "msw/node";
import { sampleHandlers } from "../handlers/sample";

// mswの設定
export const server = setupServer(...sampleHandlers);

※ハンドラーファイルを追加した際はsetupServerに追加して下さい。

 

次にファイル「vitest.setup.ts」にmswの設定を追加します。

import "@testing-library/jest-dom";
// mswの設定追加
import { afterAll, afterEach, beforeAll } from "vitest";
import { server } from "./src/lib/msw/setup/server";

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

 

次に以下のコマンドを実行し、Storybookなどのブラウザ用の設定ファイルを追加します。

$ pnpm exec msw init public --save

※実行後、ファイル「public/mockServiceWorker.js」が追加されます。

 

次に作成されたファイルをBiome(format・lintツール)のチェック対象から外すため、ファイル「biome.json」の「files」に「”!public/mockServiceWorker.js”」を追加します。

{

・・・

  "files": {
    "ignoreUnknown": true,
    "includes": [

      ・・・

      "!src/stories",
      "!public/mockServiceWorker.js"
    ]
  },

・・・

 

次にStorybookでmswを使えるようにするため、ファイル「.storybook/preview.ts」を以下のように修正します。

・・・

// mswの設定追加
import { initialize, mswLoader } from "msw-storybook-addon";
import { sampleHandlers } from "@/lib/msw/handlers/sample";

// mswの初期化
initialize({ onUnhandledRequest: "warn" }, [
  ...sampleHandlers,
]);

const preview: Preview = {
  // mswの設定追加
  loaders: [mswLoader],

・・・

};

export default preview;

※ハンドラーファイルを追加した際はinitializeに追加して下さい。

 

playwrightの設定

次にplaywrightの設定をしていきます。

まずは以下のコマンドを実行し、設定ファイルを追加します。

$ touch playwright.config.ts

 

次に作成したファイル「playwright.config.ts」を以下のように記述します。

import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./tests/e2e",

  use: {
    baseURL: "http://localhost:3000",
    headless: true,
  },

  webServer: {
    command: "pnpm dev",
    url: "http://localhost:3000",
    reuseExistingServer: !process.env.CI,
  },
});

 

次にplaywrightを実行した際に作成されるファイルをgitの管理対象外にするため、ファイル「.gitignore」に以下を追加しておきます。

・・・

# playwright
test-results/
playwright-report/

 

lefthookの導入(任意)

次にチーム開発向けにbiomeのチェックやテストを自動化するため、Gitフック管理ツールを導入します。

フロントエンド開発ではよくhuskyなどが使われますが、今回はGo言語製で他のプログラミング言語でも使いやすい「lefthook」を使います。

まずは以下のコマンドを実行し、lefthookをインストールします。

$ pnpm add -D lefthook

 

次に承認が必要になるため、以下のコマンドを実行して承認して下さい。

$ pnpm approve-builds

 

次に以下のコマンドを実行し、lefthookを初期化します。

$ pnpm exec lefthook install

 

次に作成されたファイル「lefthook.yml」を以下のように修正します。

pre-commit:
  parallel: true
  commands:
    biome:
      run: pnpm check

pre-push:
  parallel: false
  commands:
    unit-test:
      run: pnpm test
    e2e-test:
      run: pnpm test:e2e

 

各種コマンド一覧

・Storybookの起動(UIカタログ)

pnpm storybook

 

・ローカルサーバー起動(Next.jsアプリ)

pnpm dev

 

・biome check(フォーマット修正・import整理・lint)実行

pnpm check

 

・テスト「unit/integration」実行

pnpm test

 

・テスト「e2e」実行(UIなし)

pnpm test:e2e

 

・テスト「e2e」実行(UIあり)

pnpm test:e2e:ui

※もしplaywrightのブラウザのインストールが必要なら「pnpm exec playwright install」を実行して下さい。

 

その他のライブラリについて

その他、必要に応じて以下のようなライブラも追加して下さい。

・フォーム用ライブラリ「react-hook-form」

$ pnpm add react-hook-form @hookform/resolvers

 

・バリデーション用ライブラリ「zod」

$ pnpm add zod

 

・React向けのデータ取得・キャッシュ管理ライブラリ「swr」

$ pnpm add swr

 



OpenAI「Codex」におけるハーネスエンジニアリング設定

AI駆動開発をする際には何らかのAIツールを利用しますが、今回はOpenAIの「Codexアプリ」または「Codex CLI」を利用する前提としています。

そしてAIツールを上手く使って開発するためには『ハーネスエンジニアリング』が重要になっており、事前にしっかりハーネス設計をする必要があります。

 

ハーネスエンジニアリングとは?

AIツールにおける『ハーネスエンジニアリング』とは、AIモデルやAIエージェントを安全かつ安定して動作させるため、入力・出力の制御やルール設定、評価・テストの仕組みなどを設計・構築する技術のことです。

これによってAIの挙動を管理し、品質や再現性を担保した状態で実運用できるようにします。

 

OpenAI「Codex」におけるハーネス設計について

OpenAI「Codex」でハーネス設計をしたい場合は、以下のようなディレクトリ構成で各種ファイルを作成し、それぞれ内容を定義していくことになります。

/my-project
 ├── /.codex
 |    ├── config.toml  ※codexに関する設定
 |    |
 |    ├── /rules  ※sandbox外で実行できるコマンド制御の設定
 |    |    └── default.rules
 |    |
 |    ├── /agents  ※サブエージェントを利用する場合の例
 |    |    ├── orchestrator.toml  ※指揮者(全体制御)
 |    |    ├── tester.toml        ※テスター(テストコード作成・検証)
 |    |    ├── implementer.toml   ※実装者(テストコードを通すように実装)
 |    |    └── reviewer.toml      ※レビュワー(設計や品質チェック)
 |    |
 |    ├── /workflows  ※ワークフローを利用する場合の例
 |    |    └── sdd_flow.md  ※SDD(Storybook Driven Development)のフロー
 |    |
 |    └── /skills  ※Agent Skillsを利用する場合
 |
 ├── AGENTS.md  ※ルートディレクトリ用(共通ルール)
 |
 ├── /src
 |    └── AGENTS.md  ※サブディレクトリ用(専用ルール)
 |
 └── /docs  ※詳細仕様にファイル分割して格納(各種AGENTS.mdから指定する)
      └── /rules
           ├── architecture.md  ※設計思想のルール定義
           ├── database.md      ※DB設計のルール定義
           ├── sub.md           ※サブディレクトリ用のルール定義
           └── testing.md       ※テスト用のルール定義
 

 

codexの設定ファイルを作成

まずはcodexの設定ファイルを作成するため、以下のコマンドを実行してファイルを作成します。

$ mkdir .codex && touch .codex/config.toml

 

次に作成したファイルを以下のように記述します。

・「.codex/config.toml」

model = "gpt-5.2"
model_reasoning_effort = "medium"

sandbox_mode = "workspace-write"

※今回はモデルに「gpt-5.2」を指定(利用中のプランで使用可能なものを指定して下さい)、モデルの推論設定に「medium(バランス型)」を指定、サンドボックスモードに「workspace-write(書き込み許可)」を指定

 

尚、Codexアプリなどで対象のプロジェクトに設定した「.codex/config.toml」を有効化するには、対象のプロジェクトを信頼するプロジェクトにする必要があります。

対象のプロジェクトを信頼するプロジェクトにしたい場合は、グローバル設定の方のconfig.toml(~/.codex/config.toml)で、以下のような設定を追加して下さい。

[projects."対象のプロジェクトのフルパス"]
trust_level = "trusted"

※設定変更を反映するにはCodexアプリの再起動が必要です。

 

sandbox外のコマンド制御設定を追加

次にsandbox外で実行できるコマンドを制御するため、以下のコマンドを実行してファイルを作成します。

$ mkdir -p .codex/rules && touch .codex/rules/default.rules

 

次に作成したファイルを以下のように記述します。

・「.codex/rules/default.rules」

# --- ディスク破壊(即禁止) ---
prefix_rule(
    pattern=["mkfs", "dd if=", "wipefs"],
    decision="forbidden",
    justification="ストレージ破壊操作"
)

# --- Git履歴破壊(即禁止) ---
prefix_rule(
    pattern=["git push --force", "git push -f", "git push --force-with-lease"],
    decision="forbidden",
    justification="履歴改変(強制push)によるリポジトリ破壊の可能性"
)

# --- GitHub CLI 危険操作 ---
prefix_rule(
    pattern=["gh repo delete"],
    decision="forbidden",
    justification="リポジトリ削除(不可逆)"
)

prefix_rule(
    pattern=["gh pr merge --admin"],
    decision="ask",
    justification="保護ルール無視の強制マージ"
)

prefix_rule(
    pattern=["gh workflow run"],
    decision="ask",
    justification="CI/CDの強制実行"
)

prefix_rule(
    pattern=["gh secret set", "gh secret delete"],
    decision="ask",
    justification="機密情報の変更"
)
# --- 危険削除(確認) ---
prefix_rule(
    pattern=["rm -rf", "sudo rm"],
    decision="ask",
    justification="不可逆削除の可能性"
)

# --- 権限昇格 ---
prefix_rule(
    pattern=["sudo"],
    decision="ask",
    justification="システム影響が大きい"
)

※まずは危険なコマンドを制御する

 

agents(サブエージェント)機能を追加

次にagents(サブエージェント)機能を試すため、以下のコマンドを実行してファイルを作成します。

$ mkdir -p .codex/agents
$ touch .codex/agents/pm.toml .codex/agents/tester.toml .codex/agents/implementer.toml .codex/agents/reviewer.toml

※今回はpm(プロダクトマネージャー・指揮者)、tester(テスター)、implementer(実装者)、reviewer(レビュワー)の4名を想定しています。

 

次に作成したファイルをそれぞれ以下のように記述します。

・「.codex/agents/pm.toml」(プロダクトマネージャー / 指揮者)

name = "pm"
description = "全体の進行管理とタスク分解を行うプロダクトマネージャー"
model_reasoning_effort = "high"
sandbox_mode = "workspace-write"

developer_instructions = """
あなたは開発全体を指揮するプロダクトマネージャーです。

役割:
- 要件を整理し、タスクに分解する
- tester → implementer → reviewer の順でタスクを割り振る
- 各エージェントのアウトプットを評価し、次の行動を決める

ルール:
- 必ずTDDサイクル(RED → GREEN → REVIEW)を守る
- 不完全な実装は次に進めない
- 問題があれば前の工程に差し戻す

出力形式:
- 次に行動するエージェント名
- 依頼内容(具体的に)
"""

 

・「.codex/agents/tester.toml」(テスター)

name = "tester"
description = "テストコード作成と動作検証を行うTDDエンジニア"
model_reasoning_effort = "high"
sandbox_mode = "workspace-write"

developer_instructions = """
あなたはTDDに従うテストエンジニアです。

役割:
- 仕様に基づいたテストコードを書く(RED)
- 実装後にテストを実行し検証する(GREEN)

ルール:
- まず失敗するテストを書く(RED)
- テストは仕様を正確に表現すること
- エッジケースも考慮する
- 実装コードは書かない

出力:
- テストコード
- テストの意図説明
"""

 

・「.codex/agents/implementer.toml」(実装者)

name = "implementer"
description = "テストを通すための実装を行うエンジニア"
model_reasoning_effort = "medium"
sandbox_mode = "workspace-write"

developer_instructions = """
あなたはTDDに従う実装エンジニアです。

役割:
- テストが通る最小限の実装を書く

ルール:
- テストを通すことを最優先
- 過剰な設計をしない(YAGNI)
- テストを書かない
- リファクタは必要最低限

出力:
- 実装コード
- 実装の簡単な説明
"""

 

・「.codex/agents/reviewer.toml」(レビュワー)

name = "reviewer"
description = "仕様適合性・品質・セキュリティをレビューするエンジニア"
model_reasoning_effort = "high"
sandbox_mode = "read-only"

developer_instructions = """
あなたはコードレビュー担当です。

役割:
- 実装が仕様を満たしているか確認
- バグ・セキュリティ問題を検出
- テスト不足を指摘

観点:
- 正しさ(仕様通りか)
- セキュリティ
- 境界値・異常系
- テスト網羅性

ルール:
- 指摘は具体的に
- 再現手順を書く
- スタイル指摘は重要な場合のみ

出力:
- 指摘一覧(重要度付き)
- 修正提案
"""

 

workflows(ワークフロー)機能を追加

次にworkflows(ワークフロー)機能も試すため、以下のコマンドを実行してファイルを作成します。

$ mkdir -p .codex/workflows && touch .codex/workflows/sdd_flow.md

※今回はSDD開発を前提とします。

 

次に作成したファイルを以下のように記述します。

・「.codex/workflows/sdd_flow.md」

# SDD開発フロー(Storybook Driven Development)

フロントエンド開発における Storybook Driven Development(SDD)の標準フローを定義する。

- stories は UI仕様書として扱う。
- tests は必要に応じた振る舞い契約として扱う。
- 実装は、stories / tests のレビュー完了後に開始する。
- Storybook は最終的なUI確認およびレビュー環境として扱う。

stories は UI仕様、
tests は振る舞い契約、
実装はそれらを満たすために行う。

---

## 基本原則

### コンポーネントの作成

- コンポーネントは再利用可能なUI単位として設計すること。
- コンポーネントの作成では、まず `.stories.tsx` ファイルを先に作成する。
  - APIを利用している場合は、`.stories.tsx` 内でモック化すること。
- コンポーネントが振る舞いを持つ場合のみ `.test.tsx` ファイルを追加する。
  - `.test.tsx` ファイルを追加した際は、RED(失敗状態)で作成する。
  - APIを利用している場合はモック化すること。
    - `src/lib/msw/handlers` 内にハンドラー用のファイルを作成する。
    - `src/lib/msw/setup/server.ts` でハンドラーファイルの読み込み設定を行う。
- `.stories.tsx` および `.test.tsx` のレビュー完了前に実装を開始してはいけない。
- `.stories.tsx` および `.test.tsx` 作成完了後にレビュー可能状態にすること。
- `.stories.tsx` および `.test.tsx` のレビュー完了後、それらを満たすように実装すること。
  - 実装の際は `.test.tsx` を GREEN にすること。
  - 実装完了後、Storybook で確認可能な状態にすること。
- 実装完了後、Storybook 上で確認およびレビューを行うこと。
- 各レビューで問題があった場合は、修正して再レビューを行うこと。

---

### ページコンポーネントの作成

- 必要な各種コンポーネントの作成完了後、`page.tsx` に配置するページコンポーネントを作成すること。
- ページコンポーネントの作成では、`.stories.tsx` および `.test.tsx` を作成する。
  - APIを利用している場合はモック化すること。
  - `.test.tsx` はインテグレーションテストを含めること。
  - `.test.tsx` は RED(失敗状態)で作成すること。
- `.stories.tsx` および `.test.tsx` のレビュー完了前に実装を開始してはいけない。
- `.stories.tsx` および `.test.tsx` 作成完了後にレビュー可能状態にすること。
- `.stories.tsx` および `.test.tsx` のレビュー完了後、それらを満たすように実装すること。
  - ページコンポーネントは原則としてサーバーコンポーネントで作成すること。
  - クライアント側で状態共有が必要な場合のみクライアントコンポーネント化を許可する。
  - 実装時は `.test.tsx` を GREEN にすること。
  - 実装完了後、Storybook で確認可能な状態にすること。
- 実装完了後、Storybook 上で確認およびレビューを行うこと。
- 各レビューで問題があった場合は、修正して再レビューを行うこと。

---

### ページファイル(page.tsx)の作成

- 必要なページコンポーネントの作成完了後、ページファイル(page.tsx)を作成すること。
- 画面表示時に必要なデータ取得は、原則として page.tsx で行うこと。
- page.tsx で取得したデータはページコンポーネントへ渡すこと。
- page.tsx に複雑なUIロジックや状態管理を書いてはいけない。
- page.tsx の責務は以下に限定すること。
  - routing
  - params handling
  - fetch
  - ページコンポーネント呼び出し
- ページファイル作成完了後、ローカルサーバーを起動して動作確認およびレビューを行うこと。

---

### e2eテストの作成

- 複数ページの作成が完了し、ユーザーのユースケースを満たせる状態になった場合、必要に応じて e2e テストを作成する。
- e2eテストは必須ではない。
- e2eテストは薄く保つこと。
- e2eテストでは実装詳細ではなく、ユーザーユースケースを検証すること。
- e2eテストファイルは `tests/e2e/` 配下に `.spec.ts` として作成すること。

---

## コンポーネントの開発フロー

1. `.stories.tsx` を作成する
  - UI状態を定義する
  - 必要に応じてモックデータを作成する
  - API利用時は Storybook 用にモック化する

2. 振る舞いが必要な場合のみ `.test.tsx` を作成する
  - RED(失敗状態)で作成する
  - interaction / state change / validation を対象とする
  - API利用時は MSW でモック化する

3. `.stories.tsx` と `.test.tsx` をレビューする
  - UI仕様
  - 状態定義
  - interaction
  - accessibility
  - responsive behavior
  - test内容
  を確認する

4. `.stories.tsx` と `.test.tsx` を満たすように実装する
  - 最小実装を優先する
  - stories / tests を書き換えて通してはいけない

5. `.test.tsx` を GREEN にする
  - 全テストを成功させる
  - flaky test を作らない

6. Storybook で確認・レビューする
  - 各状態が正しく表示されること
  - visual consistency
  - accessibility
  - responsive behavior
  を確認する

7. 必要に応じてリファクタリングする
  - stories
  - tests
  を壊さないこと

---

## ページコンポーネントの開発フロー

1. 必要なコンポーネントを組み合わせて設計する

2. `.stories.tsx` を作成する
  - ページ全体のUI状態を定義する
  - Loading / Empty / Error を含める
  - API利用時はモック化する

3. `.test.tsx` を作成する
  - インテグレーションテストを含める
  - RED(失敗状態)で作成する

4. `.stories.tsx` と `.test.tsx` をレビューする
  - ユースケース
  - 状態遷移
  - interaction
  - accessibility
  - responsive behavior
  を確認する

5. `.stories.tsx` と `.test.tsx` を満たすように実装する
  - 原則としてサーバーコンポーネントで作成する
  - 必要な場合のみクライアントコンポーネント化する

6. `.test.tsx` を GREEN にする
  - インテグレーションテストを通す
  - 実装依存テストを避ける

7. Storybook で確認・レビューする
  - ページ全体の表示
  - 各状態
  - responsive behavior
  を確認する

8. 必要に応じてリファクタリングする

---

## ページファイル(page.tsx)の開発フロー

1. 必要なページコンポーネントを完成させる

2. `page.tsx` を作成する
  - routing
  - params handling
  - fetch
  - ページコンポーネント呼び出し
  のみを担当する

3. 画面表示時に必要なデータをフェッチする
  - 原則として page.tsx でフェッチする
  - フェッチしたデータをページコンポーネントへ渡す

4. loading / error handling を実装する

5. ローカルサーバーで確認・レビューする
  - routing
  - navigation
  - fetch
  - rendering
  を確認する

6. 必要に応じてリファクタリングする

---

## e2eテストの開発フロー

1. 対象ユースケースを整理する
  - ユーザー操作
  - 主要画面遷移
  - 主要機能
  を対象とする

2. `tests/e2e/` 配下に `.spec.ts` を作成する

3. ユースケースベースでテストを書く
  - 実装詳細に依存しない
  - UI内部構造に依存しない

4. 必要最小限のテストにする
  - e2eテストは薄く保つ
  - 重複テストを避ける

5. ローカル実行で確認する
  - 画面遷移
  - 入力
  - API連携
  - エラーハンドリング
  を確認する

6. flaky test を作らない
  - wait乱用禁止
  - timeout依存禁止
  - 安定した selector を使用する

---

## 完了条件

### コンポーネント

- `.stories.tsx` 作成済み
- 必要なUI状態が定義済み
- review 完了
- 実装完了
- Storybook で確認済み
- `.test.tsx` がある場合は GREEN

---

### ページコンポーネント

- `.stories.tsx` 作成済み
- Loading / Empty / Error 状態を確認済み
- review 完了
- 実装完了
- integration test がある場合は GREEN
- responsive behavior 確認済み
- Storybook で確認済み

---

### ページファイル(page.tsx)

- App Router に統合済み
- fetch 処理確認済み
- loading / error handling 実装済み
- ローカルサーバーで動作確認済み

---

### e2eテスト

- 必要なユースケースをカバー
- flaky test が存在しない
- ローカル実行で成功

 

Agent Skillsを追加(任意)

必要に応じてAgent Skillsを使うことで効率化が図れますが、例えば以下のようなスキルを利用したりします。

 

・スキル「plan-to-issue」:プランモードで作成した開発計画をGitHubのIssue用のフォーマットへ変換して自動登録する

まずは以下のコマンドを実行し、各種ファイルを作成します。

$ mkdir -p .codex/skills/plan-to-issue && touch .codex/skills/plan-to-issue/SKILL.md
$ mkdir -p .codex/skills/plan-to-issue/references && touch .codex/skills/plan-to-issue/references/rules.md
$ mkdir -p .codex/skills/plan-to-issue/assets && touch .codex/skills/plan-to-issue/assets/template.md
$ mkdir -p .codex/skills/plan-to-issue/scripts && touch .codex/skills/plan-to-issue/scripts/create_issue.sh
$ chmod +x .codex/skills/plan-to-issue/scripts/create_issue.sh

※スクリプトは「chmod +x」で実行権限を付与します。

 

次に作成したファイルをそれぞれ以下のように記述します。

・「.codex/skills/plan-to-issue/SKILL.md」

---
name: plan-to-issue
description: プランモードで作成した開発計画をGitHub Issue用フォーマットへ変換して自動登録する
---

# plan-to-issue

## 概要

このスキルは、プランモードで作成された開発計画を読み込み、定義された変換ルールに従ってGitHub Issue形式へ構造化し、自動的にGitHubへ登録する。

---

## 重要原則(最重要)

- summary(概要)は要約してよい
- tasks(タスク)は**絶対に要約してはならない(展開必須)**
- tasksは「実装可能な手順レベル」にまで分解する
- 不明点は補完しつつも、実行手順を失わないことを優先する

---

## 参照ファイル

必ず以下を読み込むこと:

- **変換ルール定義**: `references/rules.md`
- **出力テンプレート**: `assets/template.md`
- **登録スクリプト**: `scripts/create_issue.sh`

---

## 入力

プランモードで作成された開発計画(仕様・タスク・背景など)

---

## 出力

GitHub Issue(gh issue create により自動登録)

---

## 実行手順

### 1. 開発計画の解析

- 目的・背景・機能・制約を分解して理解する
- 暗黙的なタスクも抽出する

---

### 2. ルール読み込み

- `references/rules.md` を厳密に適用する

---

### 3. テンプレート適用

- `assets/template.md` に従いIssue構造を生成

---

### 4. タイトル生成

- rules.mdの命名規則に従う

---

### 5. GitHub登録

- `scripts/create_issue.sh` を使用してIssue作成

---

## 品質保証(必須チェック)

- tasksは抽象化されていないか
- 実装手順が復元可能か
- 設計・実装・テストが含まれているか

 

・「.codex/skills/plan-to-issue/references/rules.md」

# 変換ルール定義(plan-to-issue)

## 1. 基本方針

- 1 Issue = 1目的(または1成果物)
- 情報は構造化するが、**実行可能性を失わないことを最優先**
- summaryとtasksは役割を完全に分離する

---

### 最重要ルール

#### summaryとtasksの役割分離

| 項目 | 性質 | ルール |
|------|------|--------|
| summary | 要約 | 圧縮OK |
| tasks | 実行手順 | 圧縮禁止・完全展開必須 |

---

## 2. フィールド対応ルール

### 2-1 summary(概要)

- 目的ベースで1〜3文
- 実装詳細は書かない
- 要約OK

---

### 2-2 background(背景)

- 課題・理由・現状を記述
- 不足は文脈補完可

---

### 2-3 scope(スコープ)

- In Scope / Out of Scope を明示
- 暗黙スコープは必ず明文化

---

## 2-4 tasks

### 絶対ルール

#### 禁止

- 「実装する」
- 「対応する」
- 「作る」
- 「改善する」

→ これらはすべて禁止(抽象語)

---

### 必須ルール

tasksは必ず以下を満たす:

#### 1. 手順分解必須
- 設計 → 実装 → テスト → 検証の順で展開

#### 2. 最小粒度
- 1タスク = 30〜90分単位
- 1タスク = 単一アクション

#### 3. 具体動詞必須
- 「作成する」「定義する」「追加する」「検証する」

---

#### 4. 必須分解カテゴリ

必ず以下を含める:

- 仕様確認
- 設計
- データ構造定義
- 実装
- エラーハンドリング
- テスト
- 動作確認

---

#### 5. タスク展開ルール(強化)

開発計画からタスク化する際は:

- 機能を「手順」に分解
- 暗黙工程も明示化
- 一つの機能を1タスクにしない

---

#### 6. 良い例

##### 悪い
- APIを実装する

##### 良い
- API仕様(リクエスト/レスポンス)を定義する
- エンドポイントルーティングを作成する
- バリデーション処理を実装する
- DBアクセス層を実装する
- エラーハンドリングを追加する
- 単体テストを作成する
- 結合テストを実行する

---

## 2-5 acceptance_criteria

- 「できること」で記述
- 必ずテスト可能であること

例:
- 正常リクエストで200が返ること
- 不正入力でエラーが返ること

---

## 2-6 notes

- 技術制約
- 依存関係
- 未確定事項(要確認)
- 将来対応

---

## 3. タイトル生成ルール

Issueタイトルは以下のルールで生成する

### フォーマット

[種別] 内容の要約

### 種別の分類

- feat: ユーザーに価値を提供する新機能
- fix: 不具合の修正
- refactor: 挙動を変えない内部改善
- docs: ドキュメントの追加・更新
- test: テストの追加・修正
- infra: インフラ・CI/CD・環境構築
- chore: 上記に当てはまらない雑務(極力使わない)

### ルール

- 30〜60文字程度に収める
- 内容が一目で分かるようにする
- summaryの内容をベースに生成する

例:

- feat: ユーザー登録APIを実装する
- fix: ログイン時の認証エラーを修正

---

## 4. Issue分割ルール

- 10タスク以上 → 分割必須
- 独立機能は別Issue
- 依存関係はnotesへ

---

## 5. 不足情報補完

- 合理的推測OK
- 推測はnotesに明記
- 不確定は「要確認」

---

## 6. 禁止事項

- 抽象タスク
- 実行不能なタスク
- tasksの要約
- 背景なしIssue

---

## 7. 出力品質チェック

- tasksが完全手順化されている
- 抽象名詞が存在しない
- 設計〜テストが揃っている
- 実装順が復元可能

 

・「.codex/skills/plan-to-issue/assets/template.md」

## 概要
{{summary}}

## 背景
{{background}}

## スコープ
{{scope}}

## タスク
- [ ] {{tasks}}

## 受け入れ条件
- {{acceptance_criteria}}

## 補足
{{notes}}

 

・「.codex/skills/plan-to-issue/scripts/create_issue.sh」

#!/usr/bin/env bash

set -euo pipefail

# ===============================
# Usage:
# ./create_issue.sh "タイトル" "本文"
# ===============================

TITLE="${1:-}"
BODY="${2:-}"

# タイトルと本文の入力チェック
if [[ -z "$TITLE" || -z "$BODY" ]]; then
  echo "Usage: $0 \"タイトル\" \"本文\""
  exit 1
fi

# gh コマンド存在チェック
if ! command -v gh &> /dev/null; then
  echo "gh コマンドが見つかりません"
  exit 1
fi

# GitHub認証チェック
if ! gh auth status &> /dev/null; then
  echo "GitHubにログインしていません"
  echo "gh auth login を実行してください"
  exit 1
fi

echo "Issueを作成中..."

# 一時ファイル作成
TMP_FILE=$(mktemp)

# 一時ファイルをスクリプト終了時に削除
trap 'rm -f "$TMP_FILE"' EXIT

# 本文を一時ファイルに書き込み
printf "%s" "$BODY" > "$TMP_FILE"

# Issue作成
gh issue create \
  --title "$TITLE" \
  --body-file "$TMP_FILE"

echo "Issue作成完了"

 

・スキル「auto-commit」:修正したコードをステージングしたうえで差分を解析し、適切なコミットメッセージを生成してgit commitまでを自動で実行する

次に以下のコマンドを実行し、各種ファイルを作成します。

$ mkdir -p .codex/skills/auto-commit && touch .codex/skills/auto-commit/SKILL.md

 

次に作成したファイルをそれぞれ以下のように記述します。

・「.codex/skills/auto-commit/SKILL.md」

---
name: auto-commit
description: 修正したコードをステージングしたうえで差分を解析し、適切なコミットメッセージを生成してgit commitまでを自動で実行する
---

# auto-commit

## 概要
このスキルは、コード修正後の未ステージ状態から変更を検出し、自動でステージング、差分解析、コミットメッセージ生成、git commit実行までを一貫して行う。

## 処理フロー

### 1. 未ステージの変更をステージ

以下のコマンドを実行し、未ステージの変更をすべてステージする。

```bash
git add -A
```

---

### 2. ステージ済み差分の取得

以下のコマンドを実行し、ステージ済みの変更内容の差分情報を取得する。

```bash
git diff --cached
```

---

### 3. 差分解析

取得したコードの差分情報から以下を解析する:

- 変更の目的(機能追加 / バグ修正 / リファクタリング / 雑務)
- 影響範囲(ファイル・モジュール)
- ユーザー視点での変化
- 変更が単一責務かどうか

---

### 4. コミットメッセージ生成

コードの差分情報の解析結果をもとに、
Conventional Commits形式でコミットメッセージを生成する。

#### フォーマット

`<type>: <summary>`

#### type一覧

- feat: ユーザーに価値を提供する新機能
- fix: 不具合の修正
- refactor: 挙動を変えない内部改善
- docs: ドキュメントの追加・更新
- test: テストの追加・修正
- infra: インフラ・CI/CD・環境構築
- chore: 上記に当てはまらない雑務(極力使わない)

#### コミットメッセージの例

fix: ログイン時のトークン更新処理の不具合を修正

---

### 5. コミット実行

生成したコミットメッセージを用いて以下のコマンドを実行し、コミットを実行する。

```bash
git commit -m "<generated commit message>"
```

---

## 動作ルール

### 0. 実行順序

- 処理は必ず「git add → diff確認 → commit可否判定」の順で実行する
- git add は処理の最初に一度だけ実行する(追加実行は禁止)

---

### 1. 変更検知・終了条件

- 変更が存在しない場合は、git add / commit は実行せず処理を終了する
- git diff --cached の結果が空の場合も同様にコミットを行わない
- git add 後に再度差分を確認し、変更がない場合は即終了する
- 空コミットは絶対に作成しない

---

### 2. 安全性チェック(危険変更の制御)

- .env, secrets, credential系ファイルの変更が含まれる場合は必ず停止する
- 破壊的変更(大量削除・ファイル削除が多数)の場合は警告を出し、停止する

- 破壊的変更の定義:
  - 削除ファイルが5件以上
  - または差分行数の削除が追加の2倍以上

- 上記条件を満たす場合は自動実行せず、必ず停止してユーザー確認を求める

---

### 3. コミット構造ルール

- 1つのコミットは必ず単一の目的(単一責務)になるようにする
  - 複数の変更目的が混在している場合は論理的にまとめるか警告扱いとする

- 大規模変更(複数モジュールにまたがる変更)の場合は、可能であれば分割コミットを優先する

---

### 4. コミットメッセージ生成ルール

- コミットメッセージは必ず変更内容に基づいて生成し、推測や一般論で補完しない
  - 差分から読み取れない情報は含めない

- メッセージは簡潔にしつつ、変更の「意図」が分かる表現にする
  - 実装内容の羅列ではなく、何が改善されたかを優先する

- コミットメッセージは50〜72文字程度を目安にする

- 英語・日本語のどちらを使うかはプロジェクトの既存コミットに合わせて統一する

---

### 5. 変更分類ルール

- 変更内容が以下に該当する場合は chore に分類する
  - フォーマット修正のみ
  - コメント修正のみ
  - 空白・改行整理のみ
  - 自動生成ファイルの更新

---

### 6. コミット実行ルール

- commit 実行前に最終的なメッセージを内部で確定させること
- git commit は確定したメッセージのみで実行する

---

## まとめ

このスキルは以下を保証する:

- 安全な自動コミット(事故防止)
- 意味ベースのコミット生成
- 単一責務の維持
- 変更意図の明確化
- チーム規約との整合性

 

・スキル「auto-pr」:直前のコミット内容をもとにPRタイトルと本文を生成し、GitHubのPR用フォーマットへ変換して自動登録する

次に以下のコマンドを実行し、各種ファイルを作成します。

$ mkdir -p .codex/skills/auto-pr && touch .codex/skills/auto-pr/SKILL.md
$ mkdir -p .codex/skills/auto-pr/assets && touch .codex/skills/auto-pr/assets/template.md
$ mkdir -p .codex/skills/auto-pr/scripts && touch .codex/skills/auto-pr/scripts/create_pr.sh
$ chmod +x .codex/skills/auto-pr/scripts/create_pr.sh

※スクリプトは「chmod +x」で実行権限を付与します。

 

次に作成したファイルをそれぞれ以下のように記述します。

・「.codex/skills/auto-pr/SKILL.md」

---
name: auto-pr
description: 直前のコミット内容をもとにPRタイトルと本文を生成し、GitHubのPR用フォーマットへ変換して自動登録する
---

# auto-pr

## 概要

このスキルは、直前のコミット内容をもとにPRタイトルと本文を生成し、GitHubのPR用フォーマットへ変換して自動登録します。

## 参照ファイル

このスキルを実行する際は、以下のファイルを必ず読み込んで使用してください。

- PRテンプレート: `assets/template.md`
- PR作成スクリプト: `scripts/create_pr.sh`

## 入力

直前のコミット情報

## 出力

GitHubのPR(gh pr create により自動登録)

---

## 実行手順

### 1. 直前のコミット情報と変更内容を取得する

```bash
git log -1 --pretty=format:"%h%n%s%n%b"
git show --no-color
```

- git log: 意図(タイトル・背景)
- git show: 変更内容(diff)

---

### 2. 解析して以下を生成する

- summary(概要)
- background(背景・目的)
- implementation(実装内容:箇条書き)
- test_items(テスト確認項目:チェックリスト形式)
- impact(影響範囲:箇条書き)
- future_work(未対応・今後の課題:箇条書き or なし)

---

### 3. PR本文を生成する

`assets/template.md` を読み込み、以下ルールで置換する:

- {{summary}} → summary
- {{background}} → background
- {{implementation}} → implementation
- {{test_items}} → test_items
- {{impact}} → impact
- {{future_work}} → future_work

---

### 4. PRタイトルを生成する

フォーマット:

```text
auto: <summaryの短縮版>
```

---

### 5. PRを作成する

現在のブランチをGitHubへ反映し、そのブランチを元にPRを作成する。

#### 5-1. 現在のブランチをGitHubへプッシュ

```bash
git push -u origin HEAD
```

※ pushに失敗した場合は処理を中断する

#### 5-2. PR作成

`scripts/create_pr.sh` を利用し、生成したPRタイトルと本文をGitHubに登録する

---

## 補足ルール(重要)

### ■ implementation

- diff(git show)に**実際に現れた変更のみ**を記述する
- 推測は禁止

---

### ■ test_items(重要改善)

テスト観点は以下を厳守:

- コマンド実行(例: pnpm test, npm run test など)を書かない
- 「実行手段」ではなく「確認すべき振る舞い」を書く
- diffに基づいたユーザー視点の確認項目にする

#### 良い例

- [ ] ユーザー一覧が正しく取得できる
- [ ] エラー時に適切なメッセージが表示される
- [ ] 新規作成後に一覧へ反映される

#### 悪い例(禁止)

- [ ] pnpm testを実行する
- [ ] テストコマンドを通す

---

### ■ impact

- 影響範囲を事実ベースで記載する(推測禁止)

---

### ■ future_work(重要改善)

以下ルールを厳守:

- diffやコミット内容から**明確に未対応と分かる場合のみ記載**
- 推測や一般論は禁止
- 該当がない場合は必ず以下のいずれかにする:
  - `なし`
  - または空欄(推奨は「なし」)

#### 記載してよい例

- エラーハンドリングの追加が未実装
- 一部APIのリトライ処理が未対応

#### 記載NG例

- パフォーマンス改善が必要(根拠なし)
- 今後リファクタリング予定(根拠なし)

---

## 全体ルール

- implementation / impact / future_work は必ず箇条書き
- test_items は必ずチェックリスト形式(- [ ])
- diff(git show)を必ず根拠とし、推測のみで生成しない

 

・「.codex/skills/auto-pr/assets/template.md」

## 概要
{{summary}}

## 背景・目的
{{background}}

## 実装内容
- {{implementation}}

## テスト確認項目
- [ ] {{test_items}}

## 影響範囲
- {{impact}}

## 未対応・今後の課題
- {{future_work}}

 

・「.codex/skills/auto-pr/scripts/create_pr.sh」

#!/usr/bin/env bash

set -euo pipefail

# ===============================
# Usage:
# ./create_pr.sh "タイトル" "本文"
# ===============================

TITLE="${1:-}"
BODY="${2:-}"

# タイトルと本文の入力チェック
if [[ -z "$TITLE" || -z "$BODY" ]]; then
  echo "Usage: $0 \"タイトル\" \"本文\""
  exit 1
fi

# gh コマンド存在チェック
if ! command -v gh &> /dev/null; then
  echo "gh コマンドが見つかりません"
  exit 1
fi

# GitHub認証チェック
if ! gh auth status &> /dev/null; then
  echo "GitHubにログインしていません"
  echo "gh auth login を実行してください"
  exit 1
fi

echo "PRを作成中..."

# 一時ファイル作成
TMP_FILE=$(mktemp)

# 一時ファイルをスクリプト終了時に削除
trap 'rm -f "$TMP_FILE"' EXIT

# 本文を一時ファイルに書き込み
printf "%s" "$BODY" > "$TMP_FILE"

# PR作成
gh pr create \
  --title "$TITLE" \
  --body-file "$TMP_FILE"

echo "PR作成完了"

 

今回のプロジェクト用のハーネス設定

次に今回のプロジェクト用のハーネス設定を行いますが、今回はNext.jsかつSDD(Storybook Driven Development)およびTDD(Test Driven Development)を採用したやり方で開発をすることを想定しています。

今回はそれらを踏まえて各種定義ファイルを作成していく必要があるため、まずは以下のコマンドを実行し、各種ファイルを作成します。

$ mkdir -p docs/rules
$ touch docs/rules/ui.md docs/rules/testing.md docs/rules/frontend.md
$ touch src/AGENTS.md AGENTS.md

※今回はできるだけ最小構成になるようにしています。ファイル数を増やしてしっかり定義した方が、より想定外の動作やリスクを防ぐことができるようになります。

 

次に作成したファイルをそれぞれ以下のように記述します。

・「docs/rules/ui.md」(UI実装ルール)

# UI実装ルール(Storybook)

Storybookを利用したUI実装ルールを定義する。

Storybookは単なる動作確認環境ではなく、UI仕様書およびレビュー環境として扱う。

---

## 基本原則

- stories を先に作成する
- stories はUI仕様書として扱う
- Storybook 単体でレビュー可能な状態にする
- 実装前に stories をレビュー可能状態にする
- stories を満たすように実装する
- UI状態を省略しない
- mock を利用して再現可能な状態を作る
- UI状態は useEffect で作らない

---

## stories の責務

stories は以下を表現すること:

- UI状態
- interaction
- Loading状態
- Empty状態
- Error状態
- Disabled状態
- responsive behavior
- accessibility

---

## stories 作成ルール

### 1 story = 1 state

1つの story では1つの状態のみを表現すること。

悪い例:

```tsx
export const AllStates = () => (
  <>
    <Button />
    <Button disabled />
    <Button loading />
  </>
);
```

良い例:

```tsx
export const Default = {};
export const Loading = {};
export const Error = {};
export const Empty = {};
export const Disabled = {};
```

---

## 必須状態

必要に応じて以下を作成すること:

- Default
- Loading
- Empty
- Error
- Disabled
- Hover
- Active
- Selected
- Mobile
- Tablet
- Desktop
- Dark mode

---

## args を利用する

props 切り替え可能なものは args を利用すること。

固定値を大量に埋め込まないこと。

---

## controls を利用する

レビュー時に変更可能な props は controls を利用すること。

---

## mock データルール

- Storybook 上で完結するモックを作成する
- API通信を実際に行ってはいけない
- API利用時は MSW を利用する
- mock は再利用可能にする

---

## MSW 利用ルール

API利用時は MSW を利用すること。

- handler は `src/lib/msw/handlers` に配置する
- Storybook 用 mock と test 用 mock を共有可能にする
- Loading / Error / Success を切り替え可能にする

---

## レイアウトルール

- Storybook 上で崩れないこと
- 極端な margin 調整に依存しないこと
- 固定高さレイアウトを乱用しないこと

---

## responsive ルール

responsive behavior を確認可能にすること。

最低限確認する:

- Mobile
- Desktop

必要に応じて Tablet も確認すること

---

## accessibility ルール

以下を確認すること:

- keyboard interaction
- focus visibility
- aria-label
- semantic HTML
- color contrast

---

## Tailwind CSS ルール

- utility class を優先する
- className の肥大化を避ける
- 重複 class を避ける
- magic number を乱用しない
- conditional class は整理する

---

## useEffect ルール(重要)

Storybook内のUIコンポーネントにおいて useEffect は「副作用専用」として扱う。

---

### 基本原則

- UI状態の生成に useEffect を使わない
- props → state の同期に使わない
- Storybookの状態は stories / args で表現する
- UIの表示制御目的で useEffect を使わない

---

### 使用してよいケース

- ブラウザAPI操作(window / document)
- event listener の登録・解除
- 外部購読(WebSocketなど)
- DOM操作
- アニメーション制御などの純粋な副作用

---

### 使用禁止・非推奨ケース

- propsからstateを生成する処理
- loading / error などUI状態の制御
- Storybook状態の代替としてのuseEffect
- API fetch目的(Server Component / MSW優先)

---

### Storybookとの関係

- UI状態は story で定義する
- state遷移は story 切替で表現する
- useEffectで状態遷移を作らない
- mock / args で再現する

---

### 依存配列ルール

- 使用している値は必ず依存配列に含める
- eslintルールを無視しない
- stale closure を許容しない

---

### StrictMode考慮

- useEffectは開発時に2回実行される可能性がある
- 副作用は必ず冪等にすること
- 二重実行で壊れる処理は禁止

---

### クリーンアップ必須ケース

- event listener
- interval / timeout
- subscription

必ず cleanup を実装すること

---

## Component 分割ルール

以下の場合は component 分割を検討すること:

- JSX が長すぎる
- 状態責務が増えすぎている
- 再利用可能
- story が複雑になりすぎている

---

## 禁止事項

- 実装前に stories を省略する
- Loading/Error を省略する
- Storybook 上で動作確認できない状態を作る
- API実通信に依存する
- 巨大 story を作る
- 1 story で複数状態を表現する
- UI仕様未定義のまま実装する
- useEffectでUI状態を構築する

---

## レビュー観点

レビュー時は以下を確認する:

- UI仕様が十分か
- 状態が不足していないか
- responsive behavior
- accessibility
- visual consistency
- interaction
- Loading/Error handling
- useEffectの用途が適切か

 

・「docs/rules/testing.md」(テスト実装ルール)

# テスト実装ルール

フロントエンド開発におけるテスト実装ルールを定義する。

- tests は振る舞い契約として扱う
- 実装詳細ではなく、ユーザーから見た振る舞いを保証することを目的とする

---

## 基本原則

- 必要な場合のみ tests を作成する
- tests は RED(失敗状態)から開始する
- tests を満たすように実装する
- 実装詳細ではなく振る舞いをテストする
- flaky test を作らない
- mock を利用して安定したテストを作る

---

## test が必要な条件

以下を含む場合は `.test.tsx` を作成すること:

- ユーザー操作
- state変更
- form validation
- conditional rendering
- async処理
- accessibility interaction
- integration behavior

---

## test が不要なケース

以下のみの場合は test を省略可能:

- 単純な Presentational Component
- Typography wrapper
- Layout wrapper
- 静的表示のみ

---

## Unit Test ルール

Unit Test では以下を確認すること:

- interaction
- state change
- rendering
- callback
- validation

---

## Integration Test ルール

Integration Test では以下を確認すること:

- Component連携
- 状態遷移
- API integration
- form flow
- user flow

---

## E2E Test ルール

E2E Test は以下を目的とする:

- 主要ユースケース確認
- 回帰防止
- 画面統合確認

E2E Test は薄く保つこと

---

## selector ルール

selector の優先順位は以下とする:

1. role
2. label
3. text
4. placeholder
5. data-testid

可能な限り `data-testid` を避けること

---

## Mocking ルール

API利用時は MSW を利用すること。

- mock を再利用可能にする
- Storybook と test で共有可能にする
- Success / Error / Loading を切り替え可能にする

---

## MSW 利用ルール

- handler は `src/lib/msw/handlers` に配置する
- `src/lib/msw/setup/server.ts` に登録する
- 実API通信を行ってはいけない

---

## useEffect テスト上のルール(重要)

テストにおいて useEffect を含むコンポーネントは「副作用の発火タイミング」に依存しない設計にすること。

---

### 基本原則

- useEffectの実行タイミングをテストで制御しようとしない
- useEffectの内部状態を直接検証しない
- 副作用の結果のみを検証する
- render後の不安定な状態変化を前提にしない

---

### テストしてよい対象

- 副作用の「結果」(UI変化・DOM変化)
- event handler による状態変化
- ユーザー操作後の挙動

---

### テストしてはいけない対象

- useEffect の実行回数
- useEffect 内部のローカル変数
- useEffect のタイミング依存ロジック
- 非同期タイマーの内部状態

---

### 非同期 useEffect の扱い

- waitFor は最小限にする
- 安定したUI結果を待つ
- setTimeout 依存のテストは禁止
- fetch結果は MSW で制御する

---

## 非同期テストルール

- async/await を利用する
- waitFor を最小限にする
- 安定した完了条件を待つ
- timing依存を避ける

---

## accessibility テストルール

必要に応じて以下を確認すること:

- keyboard navigation
- focus movement
- aria attributes
- accessible name

---

## flaky test 防止ルール

- ランダム値に依存しない
- 時刻依存を避ける
- timeout依存を避ける
- 実ネットワーク通信を行わない
- test 間で状態共有しない
- useEffectの非同期タイミングに依存しない

---

## RED / GREEN ルール

### RED

- 失敗する test を先に作成する
- 未実装状態であることを確認する

### GREEN

- 最小実装で test を通す
- test を書き換えて通してはいけない

---

## 禁止事項

- className selector
- implementation detail のテスト
- state 内部値の直接確認
- private function のテスト
- snapshot test の乱用
- waitFor の乱用
- timeout 依存
- sleep/wait の固定時間依存
- useEffectの内部実行制御を前提にしたテスト

---

## レビュー観点

レビュー時は以下を確認すること:

- 振る舞いを保証できているか
- implementation detail に依存していないか
- flaky test の可能性がないか
- accessibility を考慮しているか
- 過剰テストになっていないか
- useEffect依存のテスト設計になっていないか

 

・「docs/rules/frontend.md」(フロントエンド開発の実装ルール)

# フロントエンド開発の実装ルール(Next.js / App Router)

Next.js の App Router を利用したフロントエンド開発の実装ルールを定義する。

各ディレクトリの責務を明確に分離し、UI・状態・データ取得・ルーティングの境界を整理することを目的とする。

---

## 基本原則

- App Router を利用する
- page.tsx は薄く保つ
- UI責務とデータ責務を分離する
- 再利用可能なUIは `src/components` に配置する
- API通信は直接 component に埋め込まない
- Server Component を優先する
- 必要な場合のみ Client Component を利用する
- Storybook でレビュー可能な構成にする

## ディレクトリ責務

### `src/app`

Next.js App Router 用ディレクトリ。

- routing
- page.tsx
- layout.tsx

---

### `src/components`

コンポーネントを管理する。

- UI Components
- Page Components
- stories
- tests

---

### `src/components/common`

共通利用するコンポーネントパーツを管理する。

- Button
- Input
- Dialog
- Card
- Table
- Form Parts

再利用可能なUIはここに配置すること。

---

### `src/contexts`

アプリ全体で共有する状態を管理する。

#### 役割

- グローバル状態管理
- アプリ横断の状態共有

#### 例

- Auth
- Theme
- Locale
- UI設定

#### 禁止事項

- フォーム状態の管理
- 一時的UI状態の管理
- コンポーネント内部状態の代替

---

### `src/hooks`

Reactロジックの再利用を管理する。

#### 役割

- UIロジックの再利用
- interactionロジックの共通化

#### 例

- useModal
- useDebounce
- useMediaQuery
- usePagination

#### 禁止事項

- UIコンポーネントの定義
- pure function(→ libへ)
- APIクライアント(→ libへ)

---

### `src/types`

アプリ全体の型定義を管理する。

#### 役割

- APIレスポンス型
- ドメイン型
- 共通UI型
- フォーム型

---

### `src/lib`

アプリに依存しない純粋な基盤コードを管理する。

#### 役割

- APIクライアント
- APIエンドポイント定義
- utils
- constants
- validators
- MSW

---

### `src/lib/api`

API関連処理を管理する。

#### 構成例

- client.ts(fetchラッパー)
- endpoints.ts(エンドポイント定義)
- users.ts(ドメイン別API)
- auth.ts

---

### `src/lib/api/endpoints.ts`

APIエンドポイントを一元管理する。

#### 目的

- URLの散在防止
- 変更の局所化
- API呼び出しの統一

#### 例

```tsx
export const endpoints = {
  users: "/api/users",
  userDetail: (id: string) => `/api/users/${id}`,
  login: "/api/auth/login",
};
```

#### 禁止事項

- コンポーネント内でURLを直接記述すること
- feature/component側でのエンドポイント定義

---

### `src/lib/msw`

MSW の設定および共通基盤。

---

### `src/lib/msw/handlers`

APIごとの mock handler を管理する。

- users.ts
- auth.ts
- posts.ts

---

### `src/lib/msw/setup/server.ts`

MSW server 設定ファイル。

handler をまとめて読み込む。

---

## App Router ルール

### page.tsx の責務

- routing
- params handling
- fetch
- Page Component 呼び出し

---

## page.tsx の禁止事項

- UIロジックの実装
- 大量の JSX
- state管理
- business logic

---

## Server Component ルール

優先して利用する。

- page.tsx
- Page Components
- fetch専用コンポーネント

---

## Client Component ルール

以下が必要な場合のみ `"use client"` を使用する。

- browser API
- event handler
- useState / useEffect
- client interaction

---

## useEffect ルール(重要)

useEffectは「副作用専用の最終手段」として扱う。

### 基本原則

- UI状態の同期目的では使用しない
- props → state のコピーに使用しない
- 可能な限り Server Component または render計算で代替する
- Reactのレンダリング結果で表現できるものには使わない

---

### 使用してよいケース

- ブラウザAPI操作(window / document)
- event listener の登録・解除
- 外部サービス購読(WebSocketなど)
- DOM依存処理
- クライアント限定の副作用

---

### 使用禁止・非推奨ケース

- propsからstateを生成する処理
- 表示状態の同期(derived state)
- 初期化ロジックの代替
- fetch目的での乱用(Server Component優先)

---

### fetchとの関係

- データ取得は原則 Server Component で行う
- useEffectでのfetchは例外的ケースのみ
- useEffect fetchはUI依存・遅延処理のみ許可

---

### 依存配列ルール

- 使用している値は必ず依存配列に含める
- eslint警告を無視しない
- stale closureを許容しない設計にする

---

### StrictMode考慮

- useEffectは開発時に2回実行される可能性がある
- 副作用は冪等性を持たせること
- 二重実行で破綻する処理は禁止

---

### クリーンアップ必須ケース

- event listener
- interval / timeout
- subscription

必ず cleanup を実装すること

---

## 状態管理ルール

状態はスコープを最小にする。

優先順位:

1. local state
2. component state
3. page state
4. contexts(必要時のみ)

---

## fetch ルール

原則として page.tsx で fetch を行う。

---

## 禁止事項

- page.tsx の肥大化
- 不要な `"use client"`
- component 内での直接API実通信
- UIとfetch責務の混在
- 巨大component
- useEffectによる過剰な状態管理

---

## レビュー観点

- 責務分離できているか
- page.tsx が薄いか
- Server/Client境界が適切か
- Storybookでレビュー可能か
- test可能な構造か
- 再利用可能か
- useEffectが適切な用途か

 

・「src/AGENTS.md」(フロントエンド開発の全体ルール)

# フロントエンド開発の全体ルール

Next.js(App Router)におけるフロントエンド開発の全体ルールを定義する。

Codex / AIエージェントを含むすべての実装は、必ずこのルールを前提として動作すること。

## 基本思想

本プロジェクトは以下を前提とする:

- Storybook Driven Development(SDD)
- Test Driven Development(TDD)
- コンポーネント中心設計
- MSWによるAPIモック前提開発
- UIとロジックの責務分離

## 参照ドキュメント

開発時は必ず以下を参照すること:

- UI実装ルール 
  → `docs/rules/ui.md`

- テストルール 
  → `docs/rules/testing.md`

- Next.js実装境界ルール 
  → `docs/rules/frontend.md`

- 実装フロー(SDD) 
  → `.codex/workflows/sdd_flow.md`

## 開発ルールの優先順位

以下の優先順位でルールを適用する:

1. AGENTS.md(本ドキュメント)
2. docs/rules/frontend.md
3. docs/rules/ui.md
4. docs/rules/testing.md
5. .codex/workflows/sdd_flow.md

## 実装フロー

実装手順の詳細は以下を参照すること:

→ `.codex/workflows/sdd_flow.md`

すべての実装は必ずこのフローに従うこと。

## ディレクトリルール

### UI

- `src/components`:UI全般
- `src/components/common`:共通UI

---

### 状態管理

- `src/contexts`:グローバル状態
- `src/hooks`:Reactロジック

---

### 型

- `src/types`:全体型定義

---

### 基盤

- `src/lib`:純粋関数・基盤処理
- `src/lib/api`:API関連
- `src/lib/msw`:モックサーバー

---

## 実装ルール

### UI実装

- 必ず Storybook を先に作成する
- stories はUI仕様書として扱う
- UI状態を省略しない
- MSWでAPIをモック化する

---

### テスト

- 振る舞いがある場合のみ test を作成する
- RED状態から開始する
- MSWを利用する
- 実装依存テストを避ける

---

### page.tsx ルール

- routingのみ担当
- fetchのみ担当
- UIロジックは禁止
- state禁止
- Page Component呼び出しのみ

---

### Server / Client ルール

#### 1. Server Component 優先

- page.tsx
- Page Components
- fetch処理

#### 2. Client Component 条件

以下の場合のみ `"use client"` を許可:

- useState / useEffect
- browser API
- event handler
- client interaction

---

## 禁止事項

以下は禁止:

- storiesなしでの実装開始
- testなしでの振る舞い実装
- APIの直接呼び出し(components内)
- UIとfetchの混在
- page.tsxの肥大化
- 不要な `"use client"`
- URLの直接記述(lib/api/endpoints以外)

## APIルール

### エンドポイント管理

APIのエンドポイントは必ず以下で管理する:

→ `src/lib/api/endpoints.ts`

#### 例

```tsx
export const endpoints = {
  users: "/api/users",
  userDetail: (id: string) => `/api/users/${id}`,
  login: "/api/auth/login",
};
```

---

### APIクライアントルール(重要)

Next.js の標準 `fetch` を優先するため、APIクライアントは必須ではない。

共通処理が必要な場合のみ、`src/lib/api/client.ts` に薄く実装する。

---

#### 役割

- エラーハンドリング統一
- JSON変換補助
- 認証ヘッダー付与
- ログ処理(必要時)

---

#### 原則

- Server Componentでは直接 fetch を使用する
- 無理にラップしない
- Next.js の fetch のキャッシュ機能を損なわない

---

### API呼び出しルール

- UI側から直接fetch禁止
- ドメインごとにAPIファイルを分割する
- endpoint は必ず `src/lib/api/endpoints.ts` を使用する

---

## MSWルール

- `src/lib/msw/handlers` にAPIモックを配置
- `src/lib/msw/setup/server.ts` で統合
- Storybook / test 両方で共有する
- 実API通信は禁止

## 品質保証ルール

コード作成・修正後は必ず以下を実行すること:

```bash
pnpm check
```

### pnpm check の目的

- フォーマット修正
- import整理
- lintチェック(静的コード解析)

## テスト実行ルール(重要)

コード修正・実装完了後は、必ず以下のテストを実行し、
すべてパスしていることを確認すること。

```bash
pnpm test
```

E2Eテストが存在する場合は、必ず以下も実行すること:

```bash
pnpm test:e2e
```

### 必須条件

- pnpm check が通ること
- pnpm test がすべてパスすること
- pnpm test:e2e がある場合はすべてパスすること
- エラー・警告が残っていないこと
- Storybookで表示崩れがないこと

## レビュー観点

AIは以下を常に確認すること:

- UI状態が不足していないか
- storiesが仕様として成立しているか
- testが振る舞いを保証しているか
- 責務分離ができているか
- fetchがUIに侵食していないか
- MSWが適切に使われているか
- page.tsxが薄いか

 

・「AGENTS.md」(全体のルール定義)

# 全体のルール定義

## 概要

本プロジェクトはマルチエージェント構成(Codex Agents)を前提とする。

- 各エージェントは、`.codex/agents` に定義されており、すべての開発はこれらの役割分担に従って実行される。 
- Codex / AIエージェントは、必ずこの AGENTS.md を起点として動作する。 
- 開発の基本思想および、各エージェント、ワークフロー、開発のルール群を参照しながら開発を行うこと。

## 開発の基本思想

本プロジェクトは以下を前提とする:

- Storybook Driven Development(SDD)
- Test Driven Development(TDD)
- コンポーネント中心設計
- MSWによるAPIモック前提開発
- マルチエージェント分業開発

---

## マルチエージェント構成

以下のエージェントが役割分担して開発を行う:

- `.codex/agents/pm.toml`
- `.codex/agents/tester.toml`
- `.codex/agents/implementer.toml`
- `.codex/agents/reviewer.toml`

---

## ブランチ運用ルール(重要)

すべての実装・修正・テスト作成は、必ずブランチを切ってから開始すること。

### ブランチ命名規則

```txt
<prefix>/<short-description>
```

例

```txt
feat/user-login-ui
fix/button-disabled-state
test/login-form-validation
refactor/api-client-cleanup
docs/storybook-guideline-update
infra/msw-setup
chore/update-dependencies
```

---

### ブランチプレフィックス定義

#### 種別の分類

- feat: ユーザーに価値を提供する新機能
- fix: 不具合の修正
- refactor: 挙動を変えない内部改善
- docs: ドキュメントの追加・更新
- test: テストの追加・修正
- infra: インフラ・CI/CD・環境構築
- chore: 上記に当てはまらない雑務(極力使わない)

---

### ブランチ作成ルール(必須)

- テスト作成前に必ずブランチを作成する
- 実装開始前に必ずブランチを作成する
- 1タスク = 1ブランチを原則とする
- ブランチは短命に保つ

---

## 各エージェントの責務定義

### PM(Product Manager)

プロダクトの要件と開発方針を定義し、全体の設計意図とタスク構造を決定するエージェント。

#### 責務
- 要件整理・仕様の定義
- ユーザーストーリー作成
- タスク分解および実行順序の決定
- 全体の指揮および各エージェントへのタスク割り振り
- 必要に応じた軽量な設計判断(実装詳細には踏み込まない)

#### 禁止事項
- 実装詳細の決定
- コンポーネント構造の強制
- コードレベル設計への介入
- テストコードの作成

---

### Tester(テスター)

仕様をテストとして具体化し、期待される振る舞いを明確に定義するエージェント。

#### 参照ルール
テスト実装ルールは `docs/rules/testing.md` を参照する

#### 責務
- テスト設計(REDフェーズ)
- テストコード作成
- 期待仕様の定義(UI・挙動・状態)
- unit / integration / e2e テスト作成と実行
- APIレスポンス仕様の定義
- モックデータの設計
- MSWシナリオの定義(成功・失敗・loadingなど)

#### 禁止事項
- 実装コードの作成
- UIコンポーネント構造の決定
- 仕様変更
- テストを通すための仕様改変

---

### Implementer(実装者)

テストとStorybookで定義された仕様を満たすために実装を行うエージェント。

#### 責務
- 実装(GREENフェーズ)
- `.stories.tsx` に基づいたUI実装
- `.test.tsx` のテストを通すための最小実装
- Storybookで確認可能な状態の構築
- 既存MSWシナリオ前提での実装

#### 原則
- 最小実装を優先する
- テストを通すことが唯一の目的
- 仕様変更は禁止

#### 禁止事項
- 仕様の変更
- テストの書き換え
- MSWシナリオの変更
- 過剰設計

---

### Reviewer(レビュワー)

品質・設計・ルール遵守の最終保証を行うエージェント。

#### 責務
- テスト観点のレビュー
- StorybookでのUIレビュー
- コードレビュー
- 設計逸脱の検出
- 品質・構造の検証
- 責務分離の確認

#### 禁止事項
- 実装修正
- テスト修正
- 仕様変更

---

## 実装ワークフロー

すべての開発は以下のワークフローに従う:

```txt
.codex/workflows/sdd_flow.md
```

## フロントエンド開発の全体ルール

フロントエンド開発の実装については、以下のファイルを起点とする:

```txt
src/AGENTS.md
```

### 詳細ルール

- UI実装ルール:`docs/rules/ui.md`
- テストルール:`docs/rules/testing.md`
- フロントエンド開発の実装ルール:`docs/rules/frontend.md`

---

## 開発フロー

1. PM:要件整理・タスク分解
2. PM:ユーザーストーリー作成
3. Tester:ブランチを切る
4. Tester:テスト設計・テストコード作成(RED)
5. Reviewer:テストコードレビュー
6. Implementer:実装(GREEN)
7. Tester:テスト実行による検証およびレビュー
8. Reviewer:最終レビュー
  - 要件を満たしているか確認
  - Storybookでコンポーネント確認(UIチェック)
  - ローカルサーバーを起動してブラウザで確認(UI・動作チェック)
    - ブラウザのデベロッパーツールのコンソールで警告やエラーを確認(必要に応じて修正する)
9. 必要に応じて修正ループ

## 禁止事項

- エージェント責務の逸脱
- implementerによる仕様変更
- tester不在の実装
- storiesなし実装
- レビューなしでの完了扱い
- UIとロジックの混在
- ブランチ未作成での作業開始

## 品質保証ルール

すべてのコード変更後は必ず以下を実行すること:

```bash
pnpm check
```

さらにテストが存在する場合:

```bash
pnpm test
```

E2Eテストが存在する場合:

```bash
pnpm test:e2e
```

---

## 必須条件

- pnpm check が通ること
- pnpm test がすべてパスすること
- pnpm test:e2e がある場合はすべてパスすること
- Storybookで破綻がないこと
- レビューで承認されていること

 

ハーネス設計の注意点

上記では様々なドキュメントを定義してハーネス設計を行なっていますが、それぞれのドキュメントは完璧なものではありません。

もし実務でハーネス設計をする必要がある場合は、それぞれのプロジェクトに応じて最適なハーネス設計をするようにして下さい。

そしてその際には、システム開発におけるあらゆる知識(アーキテクチャ、設計、言語やフレームワーク、実装方法、AIツールの使い方など)がないと良し悪しが判断できないのと、プロジェクトに応じてどうするべきかの決断を迫られることもあると思うので、その点は注意が必要です。

また、これらのドキュメントは一回作って終わりではなく、適宜改善して育てていく必要性もあると思うので、その点も注意しましょう。

 



GitHub ActionsによるCIの導入

次にCI/CDを組み込むのも試しておきたいですが、今回は本番環境などは利用しないため、CI(Continuous Integration:継続的インテグレーション)だけ導入するのを試します。

また、今回はコード管理にGitHubを利用しているので、相性がいいGitHub Actionsを利用してCIを導入していきます。

まずは以下のコマンドを実行し、設定用のファイルを作成します。

$ mkdir -p .github/workflows && touch .github/workflows/ci.yml

 

次に作成したファイルを以下のように記述します。

name: CI

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  changes:
    runs-on: ubuntu-latest

    outputs:
      app: ${{ steps.filter.outputs.app }}

    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v6

      - name: 差分チェック
        uses: dorny/paths-filter@v4
        id: filter
        with:
          filters: |
            app:
              - 'src/**'
              - 'tests/**'
              - 'public/**'

              # Next.js / build config
              - 'next.config.*'
              - 'tsconfig.json'
              - 'postcss.config.*'

              # package manager
              - 'package.json'
              - 'pnpm-lock.yaml'
              - 'pnpm-workspace.yaml'

              # lint / format
              - 'biome.json'

              # test tools config
              - 'vitest.config.*'
              - 'vitest.setup.*'
              - 'vitest.shims.*'
              - 'playwright.config.*'

  # biome check(フォーマット修正・import整理・lint)
  check:
    needs: changes
    if: needs.changes.outputs.app == 'true'
    runs-on: ubuntu-latest

    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v6

      - name: Node.jsのインストール
        uses: actions/setup-node@v6
        with:
          node-version: 24.15.0

      - name: Corepackの有効化
        run: corepack enable

      - name: Corepackでpnpmのインストール
        run: corepack prepare pnpm@10.33.2 --activate

      - name: pnpmの「store path」を取得
        id: pnpm-store
        run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT

      - name: pnpmのキャッシュを取得
        uses: actions/cache@v5
        with:
          path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: .lockから依存関係をインストール
        run: pnpm install --frozen-lockfile

      - name: biome checkを実行
        run: pnpm check

  # 「unit/integration」tests 
  unit-test:
    needs: changes
    if: needs.changes.outputs.app == 'true'
    runs-on: ubuntu-latest

    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v6

      - name: Node.jsのインストール
        uses: actions/setup-node@v6
        with:
          node-version: 24.15.0

      - name: Corepackの有効化
        run: corepack enable

      - name: Corepackでpnpmのインストール
        run: corepack prepare pnpm@10.33.2 --activate

      - name: pnpmの「store path」を取得
        id: pnpm-store
        run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT

      - name: pnpmのキャッシュを取得
        uses: actions/cache@v5
        with:
          path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: .lockから依存関係をインストール
        run: pnpm install --frozen-lockfile

      - name: テスト「unit/integration」の実行
        run: pnpm test

  # e2e tests
  e2e-test:
    needs: changes
    if: github.ref == 'refs/heads/main' && needs.changes.outputs.app == 'true'
    runs-on: ubuntu-latest

    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v6

      - name: Node.jsのインストール
        uses: actions/setup-node@v6
        with:
          node-version: 24.15.0

      - name: Corepackの有効化
        run: corepack enable

      - name: Corepackでpnpmのインストール
        run: corepack prepare pnpm@10.33.2 --activate

      - name: pnpmの「store path」を取得
        id: pnpm-store
        run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT

      - name: pnpmのキャッシュを取得
        uses: actions/cache@v5
        with:
          path: ${{ steps.pnpm-store.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: .lockから依存関係をインストール
        run: pnpm install --frozen-lockfile

      - name: playwrightのブラウザをインストール
        run: pnpm exec playwright install --with-deps

      - name: テスト「e2e」の実行
        run: pnpm test:e2e

※起動条件はプルリクエスト(PR)作成時か、mainブランチへのプッシュやマージ実行時です。加えて対象ファイルの差分変更を検知して各種処理を実行させているのと、e2eテストはmainブランチへのマージ時のみ実行させています。また、「actions/checkout@v6」や「dorny/paths-filter@v4」はnodeのバージョンが上がった際にバージョンを上げる必要がでる可能性があります。

 

これでPR作成時やmainブランチにマージするタイミングでCIが実行されます。

もしCIをスキップしたい場合は、コミットメッセージの先頭に「[skip ci]」または「[ci skip]」を付けるとスキップ処理が可能です。

 

作成したプロジェクトをGitHubのリポジトリに登録

次に上記で作成したプロジェクトをGitHubのリポジトリに登録します。

まずは以下のコマンドを実行し、コミット処理まで完了して下さい。

$ git add -A
$ git commit -m "add init"

 

コミット完了後、GitHubのリポジトリ一覧画面にある「New」から新規リポジトリを作成し、表示される実行用コマンドを使ってプロジェクトをリポジトリにプッシュして下さい。

プッシュ後、プロジェクトが反映され、かつGitHub Actionsも起動します。GitHub Actionsの詳細を確認したい場合は、メニュー「Actions」から可能です。

 

mainブランチなどの保護設定をしたい場合

実務などではmainブランチの保護設定が必要になったりしますが、その場合はリポジトリのメニューから「Settings」画面を開き、画面左のメニュー「Branches」を選択後、Branch protection rules画面が開くので、「Add branch ruleset」をクリックします。

次にRuleset Nameを入力後、Enforcement statusを「Active」に変更し、Target branchesの項目にある「Add target」から「Include by pattern」を選択します。

 

次にポップアップが表示されるので、「main」を入力して「Add Inclusion pattern」をクリックします。

 

これでTarget branchesの項目に対象のブランチ名「main」が設定されます。

 

次にマージする前にプルリクエストを必須にしたい場合は、「Require a pull request before merging」のチェックを付け、必要に応じてオプションを設定して下さい。

 

次にCIをPASS(正常終了)することを必須にしたい場合は、「Require status checks to pass」のチェックを付け、必要に応じてオプションを設定し、「Add checks」のリストからCIの対象のジョブを検索してチェックを付けて下さい。

※今回は「check」と「unit-test」のみチェックをつけます。

 

全ての設定完了後、画面下の「Create」をクリックします。

次に認証を求められるので、認証をして下さい。

※私はパスキー認証にしています。

 

これでブランチ保護設定が完了です。今回は一例ですが、他にも色々条件が付けられるので、必要に応じて任意のものを設定して下さい。

 



OpenAI「Codexアプリ」で開発する

次にAIツールにはOpenAI「Codexアプリ」を利用して開発していきます。

 

関連記事

・OpenAI Codex CLI / Codexアプリの使い方【ChatGPT時代のAI開発ツール入門】

・Ruby on Railsで始めるAI駆動開発×TDD実践|Codexとハーネスエンジニアリングで作るDDDモジュラーモノリス

 

そして、Codexアプリを利用した開発の主な流れは以下の通りです。

  1.  プランモードで開発計画を立てる(必要に応じてスキル「plan-to-issue」を使ってGitHub Issueを自動登録)
  2.  通常モードでタスク実行
  3.  タスク完了後にレビュー(必要に応じて修正を繰り返す)
  4.  レビュー完了後にスキル「auto-commit」を使って自動コミット
  5.  スキル「auto-pr」を使って自動PR作成
  6.  PRレビュー(必要に応じて修正作業)
  7.  PRレビュー完了後にmainにマージ(対象のIssueがあればクローズ)

 

コンポーネントの配置場所について

コンポーネントに関する各種ファイルを作成する際のディレクトリ構成については、一例になりますが、私は以下のような感じで作ってますので、よければ参考にどうぞ。

※尚、Next.jsでは、サーバーコンポーネントとクライアントコンポーネントがありますが、特に理由がなければサーバーコンポーネントで作ります。また、src/app/page.tsxなどのページファイルは作成したコンポーネントを配置して作るようにし、薄く作った方がいいです。

 

SDDとTDDについて

今回はSDD(Storybook Driven Development)とTDD(Test Driven Development)を採用していますが、テスト駆動開発の場合はまずUI用のストーリーファイル「.stories.tsx」や、振る舞いがある場合はテストコード「.test.tsx」を最初に作り、それをまずしっかりレビューし、レビュー完了後に実装を進めた方がいいです。

ただし、フロントエンド開発であればバックエンド開発に比べて責任範囲が狭いため、コンポーネント開発などで重要な部分がない場合においては、実装部分のコンポーネントもまとめて作っても大丈夫です。

 

AI駆動開発におけるトレードオフ関係について

AI駆動開発では、できるだけ人間がコードの中身を見ない、レビューもできるだけしないというのが重要(ハーネス設計が必須)になり、それによって爆発的な開発スピードを実現できるようになります。

ただし、それに伴って品質に課題が出る可能性があるため、ここはスピードを取るか、品質を取るかのトレードオフ関係があります。

フロントエンド開発ではスピード重視で問題ないケースが多いと思いますが、バックエンド開発などではスピードよりも品質が最重視されることが多いのでその点は注意が必要です。

その場合は、TDDを採用するならしっかりテストコードをレビューして作り込み、その上で実装をし、必要に応じてパフォーマンスの観点等でリファクタリングするのが大事になります。

 

開発例:GitHubリポジトリを検索できるアプリケーション

今回は例として、GitHubリポジトリを検索できるアプリケーションを開発しました。

 

リポジトリを検索すると一覧で表示されるので、対象のリポジトリをクリックします。

※リポジトリの検索については、GitHubのパブリックAPIの「https://api.github.com/search/repositories」を利用しています。

 

クリック後、リポジトリの詳細が確認できます。

画面左上のタイトルロゴをクリックするとトップページ画面に戻れます。

※リポジトリの詳細情報取得については、GitHubのパブリックAPIの「https://api.github.com/repos/${owner}/${repo}」を利用しています。

 

トップページ画面に戻っても元の検索結果が表示されるようにしています。

※キャッシュ関連ではReact向けのデータ取得・キャッシュ管理ライブラリ「swr」を利用しています。

 

尚、今回私が試した際の作業時間のサマリについては、以下のような結果になりました。

タスク 作業時間
開発環境の初期セットアップ 約10時間
ハーネス設計 約10時間
AIツールのプランモードによるタスク分解・Issue登録 ※全12Issue登録 約10時間
AI駆動開発(タスク実行) 約10時間
合計 約40時間

 

タスクを実行する前の準備等で約30時間かかりましたが、タスク実行部分については全12Issue(通常だと最低でも12営業日ぐらいかかる量)を約10時間で完了できたため、単純に計算しても約10倍の開発効率アップを実現できました!

※12日 × 8時間 ÷ 10時間 = 9.6 ≒ 10

 

凄い!!

 

e2eテストも作って試す

コンポーネントを作る際は必要に応じて(振る舞いがある場合)「.test.tsx」を作り、src/app/page.tsxなどのページファイルを作った際は、必要に応じて「tests/integration」配下にintegrationテスト用の「.test.tsx」を作ります。

そして、ユーザーのユースケース(システムを使って目的を達成する具体的な「利用場面」や「一連の手順」のこと)を満たせるような画面や機能が揃ったら、「tests/e2e」配下にe2eテスト用の「.spec.ts」を作ります。

今回はStorybookの導入の際に合わせてe2eテスト用のPlaywrightも導入しているため、e2eテストを作った際は、以下のコマンドを使ってe2eテストを実行できます。

・e2eテスト実行(UIなし)

$ pnpm test:e2e

 

・e2eテスト実行(UIあり)

$ pnpm test:e2e:ui

 

特にUIありのe2eテストを実行すると、以下のように画面でデバッグなどもできるため、有効活用して下さい。

※尚、e2eテストはユースケース単位で薄く作ります。外部APIを利用している場合は、「.spec.ts」ファイル内で「await page.route()」を利用してモック化もできます。

 



最後に

今回はNext.jsによるAI駆動開発の実践方法についてご紹介しました。

実際に試してみて開発効率が約10倍になった点も踏まえ、Next.jsのフロントエンド開発についてもAI駆動開発に対応できました。

これからのシステム開発ではAI駆動開発が必須になっていくので、興味がある方はぜひ参考にしてみて下さい!

 









シェアはこちらから


【2025年】おすすめのゲーミングPC

モンハンワイルズの発売日とPC版(Steam版)の推薦スペックが公開されたので、おすすめのゲーミングPCをご紹介!


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です