AgentSkillsCN

architecture-guard

监控架构规范的遵守情况,及时发现并纠正违规行为。 适用于新功能开发、代码重构以及代码评审等场景。在检查目录结构、依赖关系和分层隔离时发挥重要作用。 触发关键词:“架构”、“结构”、“设计”、“何处放置”。

SKILL.md
--- frontmatter
name: architecture-guard
description: |
  アーキテクチャ規約の遵守を監視し、違反を検出。
  新機能追加、リファクタリング、コードレビュー時に使用。
  ディレクトリ構造、依存関係、レイヤー分離のチェック。
  「アーキテクチャ」「構造」「設計」「どこに置く」で発動。
allowed-tools: Read, Grep, Glob, Bash

アーキテクチャガードスキル

プロジェクト構造規約

Next.js App Router構成(推奨)

code
src/
├── app/                    # ルーティング(App Router)
│   ├── (auth)/            # 認証が必要なルートグループ
│   │   ├── dashboard/
│   │   └── settings/
│   ├── (public)/          # 公開ルートグループ
│   │   ├── login/
│   │   └── register/
│   ├── api/               # API Routes
│   │   └── users/
│   │       └── route.ts
│   ├── layout.tsx         # ルートレイアウト
│   └── page.tsx           # トップページ
├── components/
│   ├── ui/                # 汎用UI(Button, Input等)
│   ├── features/          # 機能別コンポーネント
│   │   └── auth/
│   │       ├── LoginForm.tsx
│   │       └── index.ts
│   └── layouts/           # レイアウトコンポーネント
├── lib/                   # ユーティリティ、設定、クライアント
│   ├── utils.ts
│   ├── prisma.ts
│   └── auth.ts
├── hooks/                 # カスタムフック
│   └── useAuth.ts
├── services/              # APIクライアント、外部サービス連携
│   └── userService.ts
├── types/                 # 型定義
│   └── user.ts
├── constants/             # 定数
│   └── routes.ts
└── styles/                # グローバルスタイル
    └── globals.css

依存関係ルール(レイヤードアーキテクチャ)

依存の方向(上から下のみ許可)

code
app/
  ↓
components/
  ↓
hooks/
  ↓
services/
  ↓
lib/
  ↓
types/ & constants/

禁止される依存パターン

bash
# 1. components/ → app/ への逆依存
grep -rn "from ['\"]@/app" src/components/ --include="*.ts" --include="*.tsx"

# 2. services/ → components/ への逆依存
grep -rn "from ['\"]@/components" src/services/ --include="*.ts"

# 3. lib/ → services/ への逆依存
grep -rn "from ['\"]@/services" src/lib/ --include="*.ts"

# 4. hooks/ → components/ への逆依存
grep -rn "from ['\"]@/components" src/hooks/ --include="*.ts"

コンポーネント設計規約

Container/Presentationalパターン

code
features/
└── user-profile/
    ├── UserProfileContainer.tsx  # データ取得、状態管理
    ├── UserProfileView.tsx       # 純粋なUI(props only)
    ├── useUserProfile.ts         # カスタムフック
    ├── types.ts                  # 型定義
    └── index.ts                  # 公開API(re-export)

index.ts の書き方

typescript
// features/user-profile/index.ts
export { UserProfileContainer as UserProfile } from './UserProfileContainer';
export type { UserProfileProps } from './types';

禁止パターン

1. UIコンポーネント内でのAPI呼び出し

typescript
// ❌ Bad: UIコンポーネント内でfetch
export function UserCard({ userId }: Props) {
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetch(`/api/users/${userId}`).then(/* ... */);
  }, [userId]);
  return <div>{user?.name}</div>;
}

// ✅ Good: カスタムフックに分離
export function UserCard({ userId }: Props) {
  const { user, isLoading } = useUser(userId);
  return <div>{user?.name}</div>;
}

2. 巨大ファイル(300行超)

bash
# 検出コマンド
find src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 300 {print}'

3. 循環依存

bash
# 検出コマンド
npx madge --circular src/

4. 未使用エクスポート

bash
# 検出コマンド
npx ts-prune

5. 深いインポートパス

typescript
// ❌ Bad: 深い相対パス
import { Button } from '../../../components/ui/Button';

// ✅ Good: エイリアス使用
import { Button } from '@/components/ui/Button';

新機能追加時のガイドライン

Q: 新しいページを追加する場合

A: src/app/ 配下に配置

  • 認証が必要: src/app/(auth)/[page-name]/page.tsx
  • 公開ページ: src/app/(public)/[page-name]/page.tsx

Q: 新しいコンポーネントを追加する場合

A: 用途に応じて配置

  • 汎用UI: src/components/ui/[ComponentName].tsx
  • 機能固有: src/components/features/[feature-name]/
  • レイアウト: src/components/layouts/[LayoutName].tsx

Q: 新しいAPIを追加する場合

A: src/app/api/ 配下に配置

  • REST規約に従う: src/app/api/[resource]/route.ts
  • 動的パラメータ: src/app/api/[resource]/[id]/route.ts

Q: 新しいフックを追加する場合

A: src/hooks/ に配置

  • 命名: use[PascalCase].ts
  • 例: useAuth.ts, useLocalStorage.ts

Q: 新しい型定義を追加する場合

A: src/types/ に配置

  • ドメインごとにファイル分割: user.ts, product.ts
  • 共通型: common.ts

違反検出コマンド集

bash
# 全チェック実行
echo "=== 依存関係チェック ==="
grep -rn "from ['\"]@/app" src/components/ --include="*.ts" --include="*.tsx" || echo "OK: components → app 違反なし"
grep -rn "from ['\"]@/components" src/services/ --include="*.ts" || echo "OK: services → components 違反なし"

echo "=== ファイルサイズチェック ==="
find src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 300 {print "WARNING:", $2, "is", $1, "lines"}'

echo "=== 循環依存チェック ==="
npx madge --circular src/ 2>/dev/null || echo "madgeが未インストール"

echo "=== 未使用エクスポートチェック ==="
npx ts-prune 2>/dev/null | head -20 || echo "ts-pruneが未インストール"

出力フォーマット

markdown
## アーキテクチャ監査結果

### ✅ 準拠項目
- ディレクトリ構造: OK
- レイヤー依存関係: OK
- ファイルサイズ: OK

### ❌ 違反項目
| ファイル | 違反タイプ | 詳細 | 修正案 |
|---------|-----------|------|--------|
| UserProfile.tsx | サイズ超過 | 450行 | Container/View分割 |
| api.ts → Button | 逆依存 | services→components | インターフェース抽出 |
| A → B → A | 循環依存 | 相互参照 | 共通モジュール抽出 |

### 📝 推奨アクション
1. UserProfile.tsx を分割(優先度: 高)
2. 循環依存を解消(優先度: 高)
3. 未使用エクスポートを削除(優先度: 中)

リファクタリングパターン

巨大ファイルの分割

typescript
// Before: 1ファイル400行
// UserProfile.tsx (400行)

// After: 3ファイルに分割
// UserProfileContainer.tsx (80行) - データ取得
// UserProfileView.tsx (150行) - UI
// useUserProfile.ts (50行) - ロジック
// types.ts (20行) - 型定義

循環依存の解消

typescript
// Before: A → B → A の循環
// moduleA.ts imports from moduleB.ts
// moduleB.ts imports from moduleA.ts

// After: 共通モジュール抽出
// common.ts (共通の型・関数)
// moduleA.ts imports from common.ts
// moduleB.ts imports from common.ts