diff --git a/.claude/commands/repo-maintenance.md b/.claude/commands/repo-maintenance.md index 05f7b344..a64790d4 100644 --- a/.claude/commands/repo-maintenance.md +++ b/.claude/commands/repo-maintenance.md @@ -2278,25 +2278,31 @@ fi **同期対象ファイルの分類:** -| カテゴリ | ファイル | 同期ポリシー | -| ------------ | --------------------------------------------- | ---------------------------- | -| マネージド | `.github/workflows/claude.yml` | 常に config の最新版で上書き | -| マネージド | `.github/workflows/claude-code-review.yml` | 常に config の最新版で上書き | -| マネージド | `.github/workflows/quality-gate-fallback.yml` | 常に config の最新版で上書き | -| マネージド | `.claude/hooks/block_git_no_verify.py` | 常に config の最新版で上書き | -| マネージド | `.claude/hooks/pre_git_quality_gates.py` | 常に config の最新版で上書き | -| マネージド | `.claude/hooks/post_git_push_ci.py` | 常に config の最新版で上書き | -| マネージド | `.claude/hooks/post_commit_adr_reminder.py` | 常に config の最新版で上書き | -| マネージド | `.claude/rules/development-standards.md` | 常に config の最新版で上書き | -| マネージド | `.claude/rules/git-conventions.md` | 常に config の最新版で上書き | -| マネージド | `.claude/rules/release-types.md` | 常に config の最新版で上書き | -| テンプレート | `.github/workflows/security.yml` | 差分表示 → 確認後に上書き | -| テンプレート | `.github/workflows/ci.yml` | 差分表示 → 確認後に上書き | -| テンプレート | `.github/ISSUE_TEMPLATE/*` | 欠落ファイルのみ追加 | -| テンプレート | `.github/pull_request_template.md` | 欠落時のみ追加 | +| カテゴリ | ファイル | 同期ポリシー | +| ------------ | --------------------------------------------- | ------------------------------ | +| マネージド | `.github/workflows/claude.yml` | 常に config の最新版で上書き | +| マネージド | `.github/workflows/claude-code-review.yml` | 常に config の最新版で上書き | +| マネージド | `.github/workflows/quality-gate-fallback.yml` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/block_git_no_verify.py` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/pre_git_quality_gates.py` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/post_git_push_ci.py` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/post_commit_adr_reminder.py` | 常に config の最新版で上書き | +| マネージド | `.claude/rules/development-standards.md` | 常に config の最新版で上書き | +| マネージド | `.claude/rules/git-conventions.md` | 常に config の最新版で上書き | +| マネージド | `.claude/rules/release-types.md` | 常に config の最新版で上書き | +| テンプレート | `.github/workflows/security.yml` | 差分表示 → 確認後に上書き | +| テンプレート | `.github/workflows/ci.yml` | 差分表示 → 確認後に上書き | +| テンプレート | `.github/ISSUE_TEMPLATE/*` | 欠落ファイルのみ追加 | +| テンプレート | `.github/pull_request_template.md` | 欠落時のみ追加 | +| テンプレート | `vitest.config.ts` | 欠落時のみ追加 (Vitest 採用時) | +| テンプレート | `eslint.config.mjs` | 欠落時のみ追加 (flat config) | +| テンプレート | `biome.json` | 欠落時のみ追加 (Biome 採用時) | +| テンプレート | `commitlint.config.js` | 欠落時のみ追加 | `quality-gate-fallback.yml` は `setup-team-protection.sh` がブランチ保護に登録する `Quality Gate` 必須チェックとセットで配布する。ci.yml が paths フィルタ等でスキップされた場合に PR が `Expected — Waiting for status to be reported` のまま blocked にならないよう、Pass を emit する役割を持つ。 +モダンツール 4 種 (`vitest.config.ts` / `eslint.config.mjs` / `biome.json` / `commitlint.config.js`) は `templates/testing/` `templates/eslint/` `templates/` 配下のテンプレートを欠落時のみ配置する。既存設定がある repo はそのまま尊重される。 + **マネージドファイル**: config リポジトリが正規のソースであり、プロジェクト側でカスタマイズしない前提のファイル。 **テンプレートファイル**: プロジェクト固有のカスタマイズが入る可能性があるため、差分確認を挟む。 @@ -2440,6 +2446,44 @@ if [ -f "$PR_TEMPLATE_SRC" ] && [ ! -f "$PR_TEMPLATE_DST" ]; then cp "$PR_TEMPLATE_SRC" "$PR_TEMPLATE_DST" UPDATED+=(".github/pull_request_template.md (新規追加)") fi + +# モダンツール 4 種: 採用判定 + 欠落時のみ配置 (path-mapping) +# vitest: package.json の devDependencies に vitest があれば配置候補 +# eslint flat config: eslint.config.* が無く、かつ ESLint を使っている場合 +# biome: package.json に @biomejs/biome があれば配置候補 +# commitlint: commit-msg フックを使う or commitlint 依存があれば配置候補 +declare -A MODERN_TOOLS=( + ["templates/testing/vitest.config.ts"]="vitest.config.ts" + ["templates/eslint/eslint.config.mjs"]="eslint.config.mjs" + ["templates/biome.json"]="biome.json" + ["templates/commitlint.config.js"]="commitlint.config.js" +) +for src_rel in "${!MODERN_TOOLS[@]}"; do + dst_rel="${MODERN_TOOLS[$src_rel]}" + src_file="$CONFIG_REPO/$src_rel" + dst_file="./$dst_rel" + [ ! -f "$src_file" ] && continue + # 既存の同等ファイルが既にある場合はスキップ (拡張子違いを含む) + case "$dst_rel" in + vitest.config.ts) + ls vitest.config.{ts,js,mjs,cjs} >/dev/null 2>&1 && continue + jq -e '.devDependencies.vitest // .dependencies.vitest' package.json >/dev/null 2>&1 || continue + ;; + eslint.config.mjs) + ls eslint.config.{mjs,js,cjs,ts} .eslintrc{.js,.json,.cjs,.yml,.yaml} >/dev/null 2>&1 && continue + jq -e '.devDependencies.eslint // .dependencies.eslint' package.json >/dev/null 2>&1 || continue + ;; + biome.json) + ls biome.json{,c} >/dev/null 2>&1 && continue + jq -e '.devDependencies["@biomejs/biome"] // .dependencies["@biomejs/biome"]' package.json >/dev/null 2>&1 || continue + ;; + commitlint.config.js) + ls commitlint.config.{js,ts,mjs,cjs} .commitlintrc{,.js,.json,.yml,.yaml} >/dev/null 2>&1 && continue + ;; + esac + cp "$src_file" "$dst_file" + UPDATED+=("$dst_rel (新規追加, モダンツールテンプレート)") +done ``` **結果パターン:** diff --git a/.claude/commands/setup-husky.md b/.claude/commands/setup-husky.md index baf896ea..ddaad7c9 100644 --- a/.claude/commands/setup-husky.md +++ b/.claude/commands/setup-husky.md @@ -88,7 +88,15 @@ fi ] } -.commitlintrc.json(リポジトリルート) +commitlint.config.js(リポジトリルート、推奨) + +`templates/commitlint.config.js` をコピーして使用: + +```bash +cp /path/to/config/templates/commitlint.config.js ./commitlint.config.js +``` + +最小構成のみ必要な場合は `.commitlintrc.json` でも可: { "extends": ["@commitlint/config-conventional"] diff --git a/.claude/commands/setup-tests.md b/.claude/commands/setup-tests.md index ffa81865..0e3ee73a 100644 --- a/.claude/commands/setup-tests.md +++ b/.claude/commands/setup-tests.md @@ -179,6 +179,25 @@ npm install -D @stryker-mutator/core @stryker-mutator/jest-runner @stryker-mutat - `jest.setup.js` - テスト前セットアップ - `jest.polyfills.js` - Web API ポリフィル +### 4.1.b Vitest を選択する場合 + +Jest の代わりに Vitest を使うプロジェクトでは、`templates/testing/vitest.config.ts` をコピー: + +```bash +cp /path/to/config/templates/testing/vitest.config.ts ./vitest.config.ts +npm install -D vitest @vitest/coverage-v8 jsdom +npm install -D @vitejs/plugin-react # React 使用時 +mkdir -p tests && cat > tests/setup.ts <<'EOF' +import '@testing-library/jest-dom/vitest'; +EOF +``` + +Vitest 採用基準: + +- Vite ベースのプロジェクト (高速 HMR / ESM ネイティブ) +- React 19 / Next.js 15+ で Jest の互換性問題に直面した場合 +- TypeScript first / モダンな ESM プロジェクト + ### 4.2 Standard Level 追加 - `playwright.config.ts` - Playwright E2E 設定 diff --git a/eslint.config.mjs b/eslint.config.mjs index 574ff2a3..9462bf51 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,7 @@ import eslintConfigPrettier from 'eslint-config-prettier'; export default [ { - ignores: ['node_modules/', 'dist/', 'coverage/', '*.min.js'], + ignores: ['node_modules/', 'dist/', 'coverage/', '*.min.js', 'templates/'], }, js.configs.recommended, eslintConfigPrettier, diff --git a/templates/biome.json b/templates/biome.json new file mode 100644 index 00000000..99990295 --- /dev/null +++ b/templates/biome.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.8/schema.json", + "_comment": "Biome 統合フォーマッタ + リンタテンプレート。npm install -D --save-exact @biomejs/biome の後、'npx biome init' で生成される設定を本テンプレートで上書き推奨", + "files": { + "includes": [ + "**", + "!**/node_modules", + "!**/.next", + "!**/dist", + "!**/build", + "!**/coverage", + "!**/public", + "!**/.vercel", + "!**/*.min.js", + "!**/*.generated.*", + "!**/database.types.ts", + "!**/pnpm-lock.yaml", + "!**/package-lock.json", + "!**/yarn.lock", + "!**/tsconfig.tsbuildinfo" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 100, + "lineEnding": "lf" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "always", + "trailingCommas": "all" + } + }, + "json": { + "formatter": { + "trailingCommas": "none" + } + } +} diff --git a/templates/commitlint.config.js b/templates/commitlint.config.js new file mode 100644 index 00000000..7d08bf5f --- /dev/null +++ b/templates/commitlint.config.js @@ -0,0 +1,24 @@ +// commitlint テンプレート (Conventional Commits) +// +// 使い方: +// 1. プロジェクトルートに `commitlint.config.js` としてコピー +// 2. 必要な依存をインストール: +// npm install -D @commitlint/cli @commitlint/config-conventional +// 3. .husky/commit-msg に以下を追加 (setup-husky 実行で自動設定): +// npx --no-install commitlint --edit "$1" +// +// 許可される type: +// feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert +// +// scope は project 固有。CLAUDE.md / AGENTS.md の git-conventions を参照。 +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + // Subject 末尾のピリオド禁止 (デフォルト: error) + 'subject-full-stop': [2, 'never', '.'], + // 本文の最大行長 (日本語コミットの場合は緩和推奨) + 'body-max-line-length': [1, 'always', 100], + // フッターの最大行長 + 'footer-max-line-length': [1, 'always', 100], + }, +}; diff --git a/templates/eslint/eslint.config.mjs b/templates/eslint/eslint.config.mjs new file mode 100644 index 00000000..6cca298e --- /dev/null +++ b/templates/eslint/eslint.config.mjs @@ -0,0 +1,55 @@ +/** + * ESLint flat config テンプレート (TypeScript / Next.js プロジェクト向け) + * + * 使い方: + * 1. プロジェクトルートに `eslint.config.mjs` としてコピー + * 2. 必要な依存をインストール: + * npm install -D eslint typescript-eslint + * 3. (オプション) Next.js プロジェクトの場合: + * npm install -D eslint-config-next + * → 下記 Next.js セクションのコメントを外す + * 4. (オプション) 複雑度ルールを有効化: + * → complexityRules import のコメントを外す + * + * 参考: keito4/config の eslint/complexity-rules.mjs を ./eslint/ に + * コピーして import すると複雑度ガードが有効になる + */ +import tseslint from 'typescript-eslint'; +// import { complexityRules } from './eslint/complexity-rules.mjs'; +// import nextCoreWebVitals from 'eslint-config-next/core-web-vitals'; +// import nextTypescript from 'eslint-config-next/typescript'; + +export default [ + { + ignores: [ + 'node_modules/**', + '.next/**', + 'dist/**', + 'build/**', + 'coverage/**', + 'public/**', + '.vercel/**', + '**/*.generated.*', + '**/database.types.ts', + ], + }, + ...tseslint.configs.recommended, + // ...nextCoreWebVitals, + // ...nextTypescript, + { + files: ['**/*.{ts,tsx}'], + rules: { + // 警告は許容、未使用変数は _ 接頭辞で許可 + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + // 複雑度ルールを取り込む場合: + // ...complexityRules, + }, + }, +]; diff --git a/templates/testing/vitest.config.ts b/templates/testing/vitest.config.ts new file mode 100644 index 00000000..29337d05 --- /dev/null +++ b/templates/testing/vitest.config.ts @@ -0,0 +1,57 @@ +// Vitest config テンプレート +// +// 使い方: +// 1. プロジェクトルートに `vitest.config.ts` としてコピー +// 2. 必要な依存をインストール: +// npm install -D vitest @vitest/coverage-v8 jsdom +// npm install -D @vitejs/plugin-react # React 使用時 +// 3. tests/setup.ts を作成 (testing-library/jest-dom 等) +// 4. package.json scripts に追加: +// "test": "vitest run" +// "test:watch": "vitest" +// "test:coverage": "vitest run --coverage" +// +// プロジェクト固有のカスタマイズが必要な箇所はコメントで明記している。 +import { defineConfig } from 'vitest/config'; +import path from 'node:path'; + +// React プロジェクトの場合は以下を有効化: +// import react from '@vitejs/plugin-react'; + +export default defineConfig({ + // plugins: [react()], + test: { + // jsdom: ブラウザ DOM シミュレーション (React/UI テストで使用) + // node: API/サーバサイドのみのプロジェクトでは 'node' に変更 + environment: 'jsdom', + globals: true, + setupFiles: ['./tests/setup.ts'], + include: ['{src,tests,lib}/**/*.{test,spec}.{ts,tsx,js,jsx}'], + exclude: ['node_modules/**', '.next/**', 'dist/**', 'tests/e2e/**', 'tests/regression/**'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + include: ['src/**/*.{ts,tsx}', 'lib/**/*.ts'], + exclude: [ + '**/*.d.ts', + '**/*.test.{ts,tsx}', + '**/*.spec.{ts,tsx}', + '**/types.ts', + '**/types/**', + '**/__tests__/**', + '**/__mocks__/**', + ], + thresholds: { + lines: 70, + functions: 70, + branches: 70, + statements: 70, + }, + }, + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +});