create-einja-app 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +33 -0
  2. package/dist/cli.js +60 -64
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/default/.changeset/config.json +11 -0
  6. package/templates/default/.claude/hooks/einja/plan-mode-skill-loader.sh +5 -1
  7. package/templates/default/.claude/settings.json +14 -4
  8. package/templates/default/.claude/skills/_einja-general-context-loader/SKILL.md +258 -0
  9. package/templates/default/.claude/skills/_einja-output-format/SKILL.md +211 -0
  10. package/templates/default/.claude/skills/_einja-project-overview/SKILL.md +29 -0
  11. package/templates/default/.claude/skills/_einja-spec-context-loader/SKILL.md +181 -0
  12. package/templates/default/.claude/skills/cli-package-specs/SKILL.md +294 -0
  13. package/templates/default/.einja-sync.json +1 -1
  14. package/templates/default/.github/release.yml +10 -0
  15. package/templates/default/.github/workflows/changeset-status.yml +60 -0
  16. package/templates/default/.github/workflows/deploy-stable-branches.yml +289 -59
  17. package/templates/default/CLAUDE.md +50 -10
  18. package/templates/default/README.md +20 -8
  19. package/templates/default/docs/plans/agile-munching-knuth.md +161 -0
  20. package/templates/default/docs/plans/agile-riding-nova.md +158 -0
  21. package/templates/default/docs/plans/agile-wibbling-dusk.md +91 -0
  22. package/templates/default/docs/plans/ancient-watching-otter.md +152 -0
  23. package/templates/default/docs/plans/bright-sauteeing-bumblebee.md +30 -0
  24. package/templates/default/docs/plans/composed-doodling-mountain.md +362 -0
  25. package/templates/default/docs/plans/dazzling-foraging-cascade.md +32 -0
  26. package/templates/default/docs/plans/enchanted-wiggling-ember-agent-a5befd57d0ca4c7c7.md +177 -0
  27. package/templates/default/docs/plans/enchanted-wiggling-ember.md +170 -0
  28. package/templates/default/docs/plans/federated-questing-kahan.md +47 -0
  29. package/templates/default/docs/plans/flickering-pondering-hearth.md +26 -0
  30. package/templates/default/docs/plans/fluttering-snuggling-sprout.md +172 -0
  31. package/templates/default/docs/plans/generic-sleeping-snowglobe-agent-a41d8da.md +179 -0
  32. package/templates/default/docs/plans/generic-sleeping-snowglobe.md +108 -0
  33. package/templates/default/docs/plans/generic-snuggling-pudding.md +57 -0
  34. package/templates/default/docs/plans/glistening-conjuring-cascade.md +42 -0
  35. package/templates/default/docs/plans/idempotent-wiggling-cherny.md +122 -0
  36. package/templates/default/docs/plans/linear-gathering-hejlsberg.md +596 -0
  37. package/templates/default/docs/plans/recursive-fluttering-mitten.md +176 -0
  38. package/templates/default/docs/plans/todo-create-einja-app-ux-fix.md +16 -0
  39. package/templates/default/docs/plans/todo-direnv-hang-fix.md +12 -0
  40. package/templates/default/docs/plans/todo-github-actions-release-workflow.md +34 -0
  41. package/templates/default/docs/plans/todo-glistening-conjuring-cascade.md +20 -0
  42. package/templates/default/docs/plans/todo-issue-spec-rename.md +24 -0
  43. package/templates/default/docs/plans/todo-skill-creator-upgrade.md +18 -0
  44. package/templates/default/docs/plans/todo-unified-crafting-valiant.md +23 -0
  45. package/templates/default/docs/plans/unified-crafting-valiant.md +60 -0
  46. package/templates/default/docs/plans/velvety-chasing-spark.md +28 -0
  47. package/templates/default/docs/plans/wondrous-strolling-crystal-agent-a0615fc.md +215 -0
  48. package/templates/default/docs/plans/wondrous-strolling-crystal.md +182 -0
  49. package/templates/default/docs/plans/zesty-roaming-steele.md +74 -0
  50. package/templates/default/gitignore +6 -2
  51. package/templates/default/package.json +6 -2
  52. package/templates/default/pnpm-lock.yaml +547 -0
  53. package/templates/default/scripts/ensure-serena.sh +28 -9
  54. package/templates/default/scripts/env-rotate-secrets.ts +66 -6
  55. package/templates/default/scripts/init-github.ts +363 -0
  56. package/templates/default/scripts/init.sh +11 -5
  57. package/templates/default/scripts/setup-dev.ts +16 -1
  58. package/templates/default/.claude/hooks/einja/validate-git-commit.sh +0 -239
  59. package/templates/default/.claude/skills/create-einja-app-release/SKILL.md +0 -186
  60. package/templates/default/.claude/skills/dev-cli-release/SKILL.md +0 -173
  61. package/templates/default/.cursor/commands/spec-create.md +0 -227
  62. package/templates/default/.cursor/commands/task-exec.md +0 -287
  63. package/templates/default/.cursor/commands/update-docs-by-task-specs.md +0 -448
  64. package/templates/default/packages/server-core/src/__generated__/fabbrica/index.d.ts +0 -270
  65. package/templates/default/packages/server-core/src/__generated__/fabbrica/index.js +0 -484
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: _einja-spec-context-loader
3
+ description: "spec(仕様書)が存在する場合の文脈収集を担当するSkill。requirements.md、design.md、qa-tests/から要件・設計・テスト仕様を抽出し、構造化して返却します"
4
+ allowed-tools:
5
+ - Read
6
+ - Grep
7
+ - Glob
8
+ ---
9
+
10
+ # spec-context-loader Skill: 仕様書からの文脈収集
11
+
12
+ あなたは仕様書分析のスペシャリストで、ATDD(受け入れテスト駆動開発)とドキュメント駆動開発に精通しています。構造化された仕様書から必要な情報を効率的に抽出し、実装に必要な文脈を提供します。
13
+
14
+ ## 中核的な責務
15
+
16
+ spec-create で作成された仕様書(requirements.md、design.md、qa-tests/)から、タスク実装に必要な文脈情報を抽出・構造化します。
17
+
18
+ ---
19
+
20
+ ## 入力
21
+
22
+ **必須パラメータ**:
23
+ - `spec_dir`: spec ディレクトリのパス(例: `/docs/specs/issues/auth/issue21-login-feature/`)
24
+ - `ac_ids`: 対象AC番号(例: `AC1.1, AC1.2`)
25
+
26
+ **入力形式**: 自然言語でAC情報を指定
27
+
28
+ ---
29
+
30
+ ## 実行手順(4ステップ)
31
+
32
+ ### ステップ1: spec ディレクトリの検証
33
+
34
+ 1. 指定された `spec_dir` の存在を確認
35
+ 2. 以下のファイルの存在を確認:
36
+ - `requirements.md` または `requirements/README.md`
37
+ - `design.md` または `design/README.md`
38
+ - `qa-tests/scenarios.md`
39
+ 3. 不足ファイルがある場合はエラーを返却
40
+
41
+ ---
42
+
43
+ ### ステップ2: requirements.md からの要件抽出
44
+
45
+ 1. requirements.md を読み込む
46
+ 2. 以下の情報を抽出:
47
+ - **ユーザーストーリー**: 該当タスクに関連するストーリー
48
+ - **受け入れ条件(AC)**: `AC{N}.{M}` 形式のすべての受け入れ基準
49
+ - **検証レベル**: 各ACの `Unit` / `Integration` / `E2E` 分類
50
+ - **非機能要件**: パフォーマンス、セキュリティ等の制約
51
+
52
+ **パース対象**: `**ACx.y**: [要約文]` + インデントGiven-When-Then形式の受け入れ条件(`- Given:` / `- When:` / `- Then:` / `- 検証レベル:` の箇条書き形式)
53
+
54
+ ---
55
+
56
+ ### ステップ3: design.md からの設計仕様抽出
57
+
58
+ 1. design.md を読み込む
59
+ 2. 以下の情報を抽出:
60
+ - **アーキテクチャ**: 使用するパターン、レイヤー構造
61
+ - **データ構造**: 型定義、インターフェース、Prismaモデル
62
+ - **API仕様**: エンドポイント、リクエスト/レスポンス形式
63
+ - **コンポーネント設計**: 画面構成、状態管理
64
+ - **エラーハンドリング方針**: エラー分類、処理方法
65
+
66
+ ---
67
+
68
+ ### ステップ4: qa-tests/ からのテスト仕様抽出
69
+
70
+ 1. AC番号からストーリー番号を特定し、テストファイルを参照
71
+ - 例: AC1.1 → Story 1 → `qa-tests/story1.md`、AC2.3 → Story 2 → `qa-tests/story2.md`
72
+ 2. scenarios.md から該当タスクのシナリオテストを確認
73
+ 3. 以下の情報を抽出:
74
+ - **テストシナリオ**: 実行すべきテストケース
75
+ - **確認項目**: 各シナリオの検証ポイント
76
+ - **実施タイミング**: 部分実行/完全実行の判定
77
+
78
+ ---
79
+
80
+ ## 出力形式
81
+
82
+ **成功時**: 以下のマークダウン形式で出力
83
+
84
+ ```markdown
85
+ ## コンテキスト収集結果
86
+
87
+ ### spec 情報
88
+ - **ディレクトリ**: {spec_dir}
89
+ - **対象AC**: {ac_ids}
90
+
91
+ ### 要件
92
+ #### 機能要件
93
+ - [ユーザーストーリー1の概要]
94
+ - [ユーザーストーリー2の概要]
95
+
96
+ #### 非機能要件
97
+ - [パフォーマンス要件]
98
+ - [セキュリティ要件]
99
+
100
+ #### 受け入れ条件
101
+ | AC番号 | タイトル | 検証レベル | 概要 |
102
+ |--------|---------|-----------|------|
103
+ | AC1.1 | [タイトル] | Unit | [Given-When-Then概要] |
104
+ | AC1.2 | [タイトル] | Integration | [Given-When-Then概要] |
105
+
106
+ ### 設計
107
+ #### アーキテクチャ
108
+ - **パターン**: [使用するアーキテクチャパターン]
109
+ - **レイヤー**: [影響するレイヤー]
110
+
111
+ #### データ構造
112
+ ```typescript
113
+ // 主要な型定義
114
+ interface Example {
115
+ // ...
116
+ }
117
+ ```
118
+
119
+ #### API仕様
120
+ - **エンドポイント**: `POST /api/example`
121
+ - **リクエスト**: [形式]
122
+ - **レスポンス**: [形式]
123
+
124
+ #### エラーハンドリング
125
+ - [エラー分類と処理方針]
126
+
127
+ ### テスト仕様
128
+ #### 対象テストファイル
129
+ - `qa-tests/story{N}.md`(該当ACセクション)
130
+
131
+ #### シナリオテスト
132
+ - **シナリオ1**: [概要] - 実施タイミング: [Step X-Y]
133
+
134
+ #### 確認項目
135
+ 1. [確認項目1]
136
+ 2. [確認項目2]
137
+ ```
138
+
139
+ **エラー時**: 以下の形式で出力
140
+
141
+ ```markdown
142
+ ## コンテキスト収集エラー
143
+
144
+ ### ステータス: ❌ FAILURE
145
+
146
+ ### エラー内容
147
+ - **原因**: [不足ファイル一覧 or エラー詳細]
148
+ - **推奨アクション**: `einja-issue-spec-create` Skill を実行して仕様書を完成させてください
149
+ ```
150
+
151
+ ---
152
+
153
+ ## エラー処理
154
+
155
+ | エラー種別 | 原因 | 対処 |
156
+ |-----------|------|------|
157
+ | spec ディレクトリ不在 | 指定パスが存在しない | パスを確認して再実行 |
158
+ | requirements.md 不在 | Phase 1 未完了 | `einja-issue-spec-create` Skill で Phase 1 を実行 |
159
+ | design.md 不在 | Phase 3 未完了 | `einja-issue-spec-create` Skill で Phase 3 を実行 |
160
+ | qa-tests/ 不在 | Phase 4 未完了 | `einja-issue-spec-create` Skill で Phase 4 を実行 |
161
+
162
+ ---
163
+
164
+ ## 実行制約
165
+
166
+ このSkillは `task-executer` エージェントから呼び出されます。spec が存在することが前提です。
167
+
168
+ ---
169
+
170
+ ## 連携
171
+
172
+ - **呼び出し元**: `task-executer` - コンテキスト収集フェーズ
173
+ - **代替Skill**: `general-context-loader` - spec がない場合の文脈収集
174
+
175
+ ---
176
+
177
+ **最終更新**: 2025-01-10
178
+
179
+ <!-- @einja:project-private:start id="einja-spec-context-loader-project" -->
180
+ <!-- プロジェクト固有の情報を記入 -->
181
+ <!-- @einja:project-private:end -->
@@ -0,0 +1,294 @@
1
+ ---
2
+ name: cli-package-specs
3
+ description: "@einja/dev-cli と create-einja-app のビルド・テンプレート仕様リファレンス。ファイルマッピング、マーカー仕様、コピーフィルタ条件を集約"
4
+ ---
5
+
6
+ # CLI パッケージ ビルド・テンプレート仕様リファレンス
7
+
8
+ ## 概要
9
+
10
+ このSkillは、2つのCLIパッケージのビルドパイプライン・テンプレート仕様を集約したリファレンスです。
11
+ `einja-` プレフィックスを持たないため、`presets/default/` にはコピーされません。
12
+
13
+ | パッケージ | 役割 |
14
+ |-----------|------|
15
+ | `@einja/dev-cli` (`packages/cli`) | 既存プロジェクトへの `.claude/` 設定・`docs/einja/` 同期。`einja init` / `einja sync` コマンドを提供 |
16
+ | `create-einja-app` (`packages/create-einja-app`) | 新規プロジェクトのスキャフォールディング。テンプレートからプロジェクト全体を生成 |
17
+
18
+ ---
19
+
20
+ ## 1. ビルドパイプライン
21
+
22
+ ### 1.1 `@einja/dev-cli` ビルド
23
+
24
+ `packages/cli/package.json` L21:
25
+ ```
26
+ "prebuild": "node ./scripts/generate-template.mjs && node ./scripts/copy-presets.mjs"
27
+ ```
28
+
29
+ #### Step 1: CLAUDE.md.template 生成
30
+ - **スクリプト**: `packages/cli/scripts/generate-template.mjs`
31
+ - **入力**: プロジェクトルートの `CLAUDE.md`
32
+ - **出力**: `packages/cli/presets/default/CLAUDE.md.template`
33
+ - **処理**:
34
+ 1. `@einja:excluded` マーカー内を除去(L53-56)
35
+ 2. `pnpm install` 等のコマンドをプレースホルダー(`{{INSTALL_COMMAND}}`等)に変換(L25-35, L62-69)
36
+
37
+ #### Step 2: プリセットファイルコピー + マーカーバリデーション
38
+ - **スクリプト**: `packages/cli/scripts/copy-presets.mjs`
39
+ - **処理順序**:
40
+ 1. `docs/einja/` 配下のマーカーバリデーション(L303-317)
41
+ 2. ディレクトリマッピングに基づくコピー(L47-122)
42
+ 3. 単一ファイルのコピー(L125-156)
43
+ 4. シンボリックリンク情報の `symlinks.json` 出力(L284-295)
44
+
45
+ ### 1.2 `create-einja-app` テンプレート更新
46
+
47
+ - **スクリプト**: `scripts/_template-update.ts`(ルート)
48
+ - **出力先**: `packages/create-einja-app/templates/default/`
49
+ - **処理**:
50
+ 1. `.templateignore` でフィルタリング(L93-103)
51
+ 2. `README.md` の `@einja:excluded` マーカー除去(L173-185)
52
+ 3. `package.json` の `name` → `{{projectName}}`、`description` → `{{description}}`(L108-131)
53
+ 4. `tsconfig.json` の `@repo/` → `{{packageName}}/`(L136-161)
54
+ 5. `.ts/.tsx/.js/.jsx` の import文 `@repo/` → `{{packageName}}/`(L166-168)
55
+
56
+ ### 1.3 `@einja/dev-cli` プリセット更新(開発用)
57
+
58
+ - **スクリプト**: `scripts/_cli-template-update.ts`
59
+ - **実行**: `pnpm preset:update`(`packages/cli/package.json` L30)
60
+ - **処理**: `FileCopier` クラスを使用してプロジェクト原本をCLIプリセットにコピー
61
+
62
+ ---
63
+
64
+ ## 2. ファイルマッピング
65
+
66
+ ### 2.1 `@einja/dev-cli` コピー対象(`copy-presets.mjs`)
67
+
68
+ #### ディレクトリマッピング(L47-122)
69
+
70
+ | 原本 | コピー先(`presets/default/` 配下) | 備考 |
71
+ |------|--------------------------------------|------|
72
+ | `.claude/agents/einja/` | `.claude/agents/einja/` | |
73
+ | `.claude/commands/einja/` | `.claude/commands/einja/` | |
74
+ | `.claude/skills/einja-*` | `.claude/skills/einja-*/` | 個別列挙(L62-101) |
75
+ | `.claude/hooks/einja/` | `.claude/hooks/einja/` | `cleanParent: true`(L107) |
76
+ | `docs/einja/` | `docs/einja/` | `memory/`, `cli/` を除外(L114) |
77
+ | `scripts/` | `scripts/` | `_` プレフィックスのファイルはスキップ(L247-249) |
78
+
79
+ #### 単一ファイルマッピング(L125-156)
80
+
81
+ | 原本 | コピー先 | 必須 |
82
+ |------|---------|------|
83
+ | `.claude/settings.json` | `.claude/settings.json` | Yes |
84
+ | `.mcp.json` | `.mcp.json` | No |
85
+ | `docs/einja/cli/preset.yaml` | `preset.yaml` | Yes |
86
+ | `.envrc` | `.envrc` | Yes |
87
+ | `.vscode/settings.json` | `.vscode/settings.json` | No |
88
+
89
+ #### 特殊変換
90
+
91
+ | 原本 | コピー先 | 変換内容 |
92
+ |------|---------|---------|
93
+ | `CLAUDE.md` | `CLAUDE.md.template` | `@einja:excluded` 除去 + プレースホルダー変換(`generate-template.mjs`) |
94
+
95
+ ### 2.2 `FileCopier` クラスのマッピング(`file-copier.ts`)
96
+
97
+ **ファイル**: `packages/cli/src/lib/preset-update/file-copier.ts`
98
+
99
+ `FileCopier` は `einja sync` / `preset:update` で使用される。`copy-presets.mjs`(prebuild)とは別のコピーロジック。
100
+
101
+ ディレクトリマッピング(L44-85):
102
+
103
+ | source | destination | category |
104
+ |--------|------------|----------|
105
+ | `.claude/commands` | `.claude/commands/einja` | commands |
106
+ | `.claude/agents` | `.claude/agents/einja` | agents |
107
+ | `.claude/skills` | `.claude/skills` | skills |
108
+ | `.claude/hooks` | `.claude/hooks` | hooks |
109
+ | `docs/einja/steering` | `docs/einja/steering` | docs |
110
+ | `docs/einja/templates` | `docs/einja/templates` | docs |
111
+ | `docs/einja/instructions` | `docs/einja/instructions` | docs |
112
+ | `docs/einja/example` | `docs/einja/example` | docs |
113
+
114
+ 単一ファイルマッピング(L92-104):
115
+
116
+ | source | destination | category |
117
+ |--------|------------|----------|
118
+ | `.envrc` | `.envrc` | env |
119
+ | `.vscode/settings.json` | `.vscode/settings.json` | tools |
120
+ | `package.json`(ルート) | `package.json` | root-config |
121
+
122
+ ---
123
+
124
+ ## 3. コピー対象フィルタ
125
+
126
+ ### 3.1 Skills のプレフィックスフィルタ
127
+
128
+ **ファイル**: `packages/cli/src/lib/preset-update/file-copier.ts` L194-195
129
+
130
+ ```typescript
131
+ // skillsカテゴリの場合、einja-/_einja-プレフィックスでフィルタリング
132
+ const prefixFilter = mapping.category === "skills" ? ["einja-", "_einja-"] : undefined;
133
+ ```
134
+
135
+ `.claude/skills/` 配下のトップレベルディレクトリのうち、**`einja-` または `_einja-` で始まるもの**が配布対象。
136
+
137
+ - **配布される**: `einja-task-commit/`, `einja-skill-creator/`, `_einja-project-overview/` 等
138
+ - **配布されない**: `cli-package-specs/`(このSkill自体)、その他プレフィックスなしのSkill
139
+
140
+ `copy-presets.mjs` ではディレクトリを動的スキャンし、`einja-*` / `_einja-*` パターンにマッチするものを個別エントリとしてコピーする。
141
+
142
+ ### 3.2 `_` プレフィックスフィルタ
143
+
144
+ - `copy-presets.mjs` L247-249: `_` で始まるファイル名はスキップ
145
+ - `file-copier.ts` L291: `_` で始まるファイル名はスキップ
146
+
147
+ ### 3.3 隠しファイルフィルタ(`file-copier.ts` のみ)
148
+
149
+ - L303: `.` で始まるファイル名はスキップ(単一ファイルマッピングで明示されたものを除く)
150
+
151
+ ---
152
+
153
+ ## 4. マーカー仕様
154
+
155
+ **詳細仕様書**: `packages/cli/docs/MARKER_SPECIFICATION.md`
156
+ **実装**: `packages/cli/src/lib/sync/marker-processor.ts`
157
+
158
+ ### 4.1 `@einja:excluded`
159
+
160
+ テンプレート生成時に**セクション全体を除去**するマーカー。
161
+
162
+ ```markdown
163
+ <!-- @einja:excluded:start -->
164
+ このセクション内容はテンプレートには含まれない
165
+ <!-- @einja:excluded:end -->
166
+ ```
167
+
168
+ - `generate-template.mjs` L53-56: CLAUDE.md → CLAUDE.md.template 変換時に除去
169
+ - `template-update.ts` L56-67: create-einja-app テンプレート(README.md等)で除去
170
+ - `_template-update.ts` L173-185: 同上
171
+
172
+ ### 4.2 `@einja:managed`
173
+
174
+ `einja sync` 実行時に**常にテンプレート版で上書き**されるセクション。
175
+
176
+ ```markdown
177
+ <!-- @einja:managed:start -->
178
+ 共通ルール(sync時に最新版で上書き)
179
+ <!-- @einja:managed:end -->
180
+ ```
181
+
182
+ - ID属性はオプション: `<!-- @einja:managed:start id="section-a" -->`
183
+ - `marker-processor.ts` L16-17: パース用正規表現
184
+
185
+ ### 4.3 `@einja:project-private`
186
+
187
+ `einja sync` 実行時に**初回のみ追加、以降はユーザー編集を保持**するセクション。
188
+
189
+ ```markdown
190
+ <!-- @einja:project-private:start id="commit-rules-project" -->
191
+ プロジェクト固有の設定(ユーザーが自由に編集)
192
+ <!-- @einja:project-private:end -->
193
+ ```
194
+
195
+ - **ID属性は必須**(`marker-processor.ts` L174-181 でバリデーション)
196
+ - レガシー `@einja:seed` マーカーとの後方互換あり(L44-53, L303-307)
197
+
198
+ ### 4.4 マーカーバリデーション
199
+
200
+ `packages/cli/scripts/validate-markers.mjs` がビルド時(`copy-presets.mjs` L303-317 から呼び出し)に実行。
201
+
202
+ | チェック項目 | エラータイプ |
203
+ |------------|------------|
204
+ | start/end ペア一致 | `unpaired_start` / `unpaired_end` |
205
+ | ネスト禁止 | `nested` |
206
+ | project-private に ID 必須 | `project_private_without_id` |
207
+ | ID 重複禁止 | `duplicate_id` |
208
+
209
+ ### 4.5 JSON マージ仕様
210
+
211
+ **実装**: `packages/cli/src/lib/sync/json-processor.ts`
212
+ **設定**: `.einja-sync.json` の `jsonPaths` フィールド
213
+
214
+ #### マージモード(ブラックリスト方式)
215
+
216
+ | モード | 動作 | 用途 |
217
+ |--------|------|------|
218
+ | `managed` | テンプレート値で強制上書き | テンプレートが完全管理するセクション |
219
+ | `project-private` | 完全除外(テンプレートから追加・更新しない) | プロジェクト固有のセクション |
220
+ | デフォルト | base/local/templateの3方向マージ | 上記以外の全パス |
221
+
222
+ #### ネスト指定
223
+
224
+ パスはドット区切りでネスト指定可能。`deepMergeWithPaths` の再帰により
225
+ 各レベルで jsonPaths チェックが行われる。
226
+
227
+ 例: `"project-private": { "package.json": ["devDependencies.@types/node"] }`
228
+ → devDependencies 全体は3方向マージ、@types/node のみ除外
229
+
230
+ #### 設定例
231
+
232
+ ```
233
+ jsonPaths:
234
+ managed: { ".claude/settings.json": ["plansDirectory"] }
235
+ project-private: { "package.json": ["name", "version", "private", "workspaces"] }
236
+ ```
237
+
238
+ → plansDirectory はテンプレート強制上書き
239
+ → name, version 等は完全除外
240
+ → scripts, devDependencies 等は3方向マージ
241
+
242
+ #### base スナップショット
243
+
244
+ 3方向マージには前回sync時のテンプレート内容(base)が必要。
245
+ `.einja-sync.json` の各ファイルメタデータに `baseContent` として保存。
246
+ 初回sync(base なし)はローカル優先 + テンプレート新規キーのみ追加。
247
+
248
+ #### コンフリクト
249
+
250
+ 両方が同じキーを異なる値に変更した場合:
251
+ - ローカル値を保持(安全側)
252
+ - コンソールに警告出力
253
+ - `mergeJson` の戻り値 `conflicts` 配列で呼び出し元にも通知
254
+
255
+ ---
256
+
257
+ ## 5. `post-setup.ts` 処理フロー
258
+
259
+ **ファイル**: `packages/create-einja-app/src/generators/post-setup.ts`
260
+
261
+ `create-einja-app` でプロジェクト生成後に実行されるセットアップフロー。
262
+
263
+ | Step | 処理 | 行番号 |
264
+ |------|------|--------|
265
+ | 0 | 初回セットアップ(`scripts/init.sh` 実行: Volta/Node.js/pnpm/direnv) | L57-64 |
266
+ | 1 | 依存関係インストール(`pnpm install`) + Prismaクライアント生成(`pnpm db:generate`) | L68-87 |
267
+ | 2 | 秘密鍵の自動ローテーション(`pnpm env:rotate-secrets --all --non-interactive`) | L90-99 |
268
+ | 3 | Git初期化(`git init` → `git add .` → `git commit`) | L102-113 |
269
+ | 4 | `@einja/dev-cli` 初期化(`npx @einja/dev-cli@latest init --force --no-backup`、`config.setupEinjaCli` が true の場合のみ) | L116-125 |
270
+ | 5 | 完了メッセージ表示 | L128 |
271
+
272
+ ---
273
+
274
+ ## 6. `setup-dev.ts` 処理フロー
275
+
276
+ **ファイル**: `scripts/setup-dev.ts`
277
+
278
+ 既存プロジェクトの開発環境セットアップスクリプト。
279
+
280
+ | Step | 処理 | 行番号 |
281
+ |------|------|--------|
282
+ | 1 | Volta インストール確認 | L158-191 |
283
+ | 2 | Volta シェル設定(`VOLTA_FEATURE_PNPM`) | L194-213 |
284
+ | 3 | Node.js / pnpm インストール(`volta install`) | L216-249 |
285
+ | 4 | direnv インストール確認(macOS: `brew install direnv`) | L324-355 |
286
+ | 5 | シェル設定(`direnv hook` を rc ファイルに追加) | L358-376 |
287
+ | 6 | dotenvx インストール | L379-419 |
288
+ | 7 | `.env` ファイル作成(`.env.local` から復号、worktree 対応) | L422-517 |
289
+ | 8 | `.env.personal` 作成 + `GITHUB_TOKEN` 対話設定 | L519-585 |
290
+ | 9 | direnv 有効化(`direnv allow`) | L588-594 |
291
+ | 10 | データベース起動(`docker-compose up -d postgres`) | L597-625 |
292
+ | 11 | データベース初期化(`pnpm db:generate` + `pnpm db:push`) | L610-613 |
293
+
294
+ worktree 環境では `.env.keys` をメインリポジトリから自動コピーする機能あり(L45-67, L73-90)。
@@ -3,7 +3,7 @@
3
3
  "lastSync": "2026-01-04T16:21:21.138Z",
4
4
  "templateVersion": "0.1.0",
5
5
  "files": {
6
- ".claude/commands/einja/update-docs-by-task-specs.md": {
6
+ ".claude/commands/einja/update-docs-by-issue-specs.md": {
7
7
  "hash": "6c09bb6748134849e8de535d6cdb382bfe0aeb0a3fb19730e1c7708ceaa283bc",
8
8
  "syncedAt": "2026-01-04T16:21:21.151Z"
9
9
  },
@@ -0,0 +1,10 @@
1
+ changelog:
2
+ exclude:
3
+ labels: ["dependencies", "skip-changelog"]
4
+ categories:
5
+ - title: "New Features"
6
+ labels: ["enhancement", "feature"]
7
+ - title: "Bug Fixes"
8
+ labels: ["bug", "fix"]
9
+ - title: "Other Changes"
10
+ labels: ["*"]
@@ -0,0 +1,60 @@
1
+ name: Changeset Status
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main, staging]
6
+ types: [opened, synchronize, reopened]
7
+
8
+ jobs:
9
+ changeset-check:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0
15
+
16
+ - name: Check for changesets
17
+ id: check
18
+ run: |
19
+ COUNT=$(ls .changeset/*.md 2>/dev/null | grep -cv README.md || echo 0)
20
+ echo "count=$COUNT" >> $GITHUB_OUTPUT
21
+ echo "has_changesets=$([[ $COUNT -gt 0 ]] && echo true || echo false)" >> $GITHUB_OUTPUT
22
+
23
+ - name: Comment on PR
24
+ uses: actions/github-script@v7
25
+ with:
26
+ script: |
27
+ const count = parseInt('${{ steps.check.outputs.count }}');
28
+ const hasChangesets = '${{ steps.check.outputs.has_changesets }}' === 'true';
29
+ const marker = '<!-- changeset-status -->';
30
+
31
+ let body;
32
+ if (hasChangesets) {
33
+ body = `${marker}\n### ✅ Changeset detected\n\nThis PR includes **${count}** changeset(s). A release will be created when merged.`;
34
+ } else {
35
+ body = `${marker}\n### ⚠️ No changeset found\n\nThis PR does not include a changeset. If this PR includes user-facing changes, please run:\n\n\`\`\`bash\npnpm changeset\n\`\`\`\n\nIf this change doesn't need a release (docs, CI, config), you can ignore this message.`;
36
+ }
37
+
38
+ // Find existing comment
39
+ const comments = await github.rest.issues.listComments({
40
+ owner: context.repo.owner,
41
+ repo: context.repo.repo,
42
+ issue_number: context.issue.number,
43
+ });
44
+ const existing = comments.data.find(c => c.body.includes(marker));
45
+
46
+ if (existing) {
47
+ await github.rest.issues.updateComment({
48
+ owner: context.repo.owner,
49
+ repo: context.repo.repo,
50
+ comment_id: existing.id,
51
+ body,
52
+ });
53
+ } else {
54
+ await github.rest.issues.createComment({
55
+ owner: context.repo.owner,
56
+ repo: context.repo.repo,
57
+ issue_number: context.issue.number,
58
+ body,
59
+ });
60
+ }