create-einja-app 0.3.1 → 0.3.3
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.
- package/README.md +34 -1
- package/dist/cli.js +92 -80
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/.changeset/config.json +11 -0
- package/templates/default/.claude/hooks/einja/plan-mode-skill-loader.sh +27 -0
- package/templates/default/.claude/settings.json +29 -1
- package/templates/default/.claude/skills/cli-package-specs/SKILL.md +247 -0
- package/templates/default/.einja-sync.json +1 -1
- package/templates/default/.env.personal.example +6 -2
- package/templates/default/.envrc +5 -0
- package/templates/default/.github/release.yml +10 -0
- package/templates/default/.github/workflows/changeset-status.yml +60 -0
- package/templates/default/.github/workflows/deploy-pr-preview.yml +23 -24
- package/templates/default/.github/workflows/deploy-stable-branches.yml +336 -100
- package/templates/default/.mcp.json +2 -12
- package/templates/default/.serena/project.yml +7 -0
- package/templates/default/CLAUDE.md +61 -10
- package/templates/default/README.md +22 -10
- package/templates/default/apps/admin/package.json +1 -1
- package/templates/default/apps/admin/tsconfig.json +2 -1
- package/templates/default/apps/web/package.json +1 -1
- package/templates/default/apps/web/tsconfig.json +2 -1
- package/templates/default/docs/plans/.gitkeep +0 -0
- package/templates/default/docs/plans/agile-munching-knuth.md +161 -0
- package/templates/default/docs/plans/agile-riding-nova.md +158 -0
- package/templates/default/docs/plans/agile-wibbling-dusk.md +91 -0
- package/templates/default/docs/plans/ancient-greeting-flamingo-agent-a87e67c.md +221 -0
- package/templates/default/docs/plans/ancient-greeting-flamingo-agent-ab73a1c.md +107 -0
- package/templates/default/docs/plans/ancient-greeting-flamingo.md +120 -0
- package/templates/default/docs/plans/ancient-watching-otter.md +152 -0
- package/templates/default/docs/plans/bright-sauteeing-bumblebee.md +30 -0
- package/templates/default/docs/plans/bright-stargazing-dawn.md +87 -0
- package/templates/default/docs/plans/calm-stirring-bonbon.md +196 -0
- package/templates/default/docs/plans/calm-watching-widget.md +111 -0
- package/templates/default/docs/plans/cheerful-wiggling-ullman.md +164 -0
- package/templates/default/docs/plans/compiled-humming-cherny.md +94 -0
- package/templates/default/docs/plans/composed-doodling-mountain.md +362 -0
- package/templates/default/docs/plans/dapper-launching-lynx.md +81 -0
- package/templates/default/docs/plans/dazzling-foraging-cascade.md +32 -0
- package/templates/default/docs/plans/effervescent-munching-kite-agent-ac08baf.md +672 -0
- package/templates/default/docs/plans/effervescent-munching-kite-agent-aecc373.md +442 -0
- package/templates/default/docs/plans/effervescent-munching-kite.md +263 -0
- package/templates/default/docs/plans/enchanted-wiggling-ember-agent-a5befd57d0ca4c7c7.md +177 -0
- package/templates/default/docs/plans/enchanted-wiggling-ember.md +170 -0
- package/templates/default/docs/plans/federated-questing-kahan.md +47 -0
- package/templates/default/docs/plans/fix-orphan-cleaner-review.md +25 -0
- package/templates/default/docs/plans/fix-sync-template-variables.md +162 -0
- package/templates/default/docs/plans/flickering-pondering-hearth.md +26 -0
- package/templates/default/docs/plans/fluttering-snuggling-sprout.md +172 -0
- package/templates/default/docs/plans/generic-sleeping-snowglobe-agent-a41d8da.md +179 -0
- package/templates/default/docs/plans/generic-sleeping-snowglobe.md +108 -0
- package/templates/default/docs/plans/generic-snuggling-pudding.md +57 -0
- package/templates/default/docs/plans/glimmering-giggling-sedgewick.md +126 -0
- package/templates/default/docs/plans/glittery-swimming-bachman.md +78 -0
- package/templates/default/docs/plans/happy-watching-toast.md +56 -0
- package/templates/default/docs/plans/harmonic-strolling-nebula.md +210 -0
- package/templates/default/docs/plans/idempotent-wiggling-cherny.md +122 -0
- package/templates/default/docs/plans/import-alias-refactor.md +75 -0
- package/templates/default/docs/plans/lazy-percolating-sloth-agent-abda679.md +346 -0
- package/templates/default/docs/plans/lazy-percolating-sloth.md +151 -0
- package/templates/default/docs/plans/linked-greeting-llama-agent-a7a6e5b.md +345 -0
- package/templates/default/docs/plans/linked-greeting-llama.md +467 -0
- package/templates/default/docs/plans/lovely-bubbling-rose.md +80 -0
- package/templates/default/docs/plans/optimized-watching-sprout.md +149 -0
- package/templates/default/docs/plans/peaceful-beaming-toast-agent-a292da6.md +288 -0
- package/templates/default/docs/plans/peaceful-beaming-toast-agent-a819699.md +366 -0
- package/templates/default/docs/plans/peaceful-beaming-toast-agent-ac11de2.md +474 -0
- package/templates/default/docs/plans/peaceful-beaming-toast.md +345 -0
- package/templates/default/docs/plans/purrfect-spinning-hickey-agent-ae6194c.md +300 -0
- package/templates/default/docs/plans/purrfect-spinning-hickey-agent-ae6900e.md +444 -0
- package/templates/default/docs/plans/purrfect-spinning-hickey.md +361 -0
- package/templates/default/docs/plans/recursive-fluttering-mitten.md +176 -0
- package/templates/default/docs/plans/recursive-kindling-lemon-agent-a42199e.md +186 -0
- package/templates/default/docs/plans/recursive-kindling-lemon.md +36 -0
- package/templates/default/docs/plans/seed-migration-tests.md +47 -0
- package/templates/default/docs/plans/sprightly-leaping-manatee.md +224 -0
- package/templates/default/docs/plans/stateful-wishing-lerdorf.md +161 -0
- package/templates/default/docs/plans/streamed-purring-wreath.md +40 -0
- package/templates/default/docs/plans/synthetic-percolating-pearl.md +101 -0
- package/templates/default/docs/plans/todo-create-einja-app-ux-fix.md +16 -0
- package/templates/default/docs/plans/todo-direnv-hang-fix.md +12 -0
- package/templates/default/docs/plans/todo-fix-sync-template-variables.md +21 -0
- package/templates/default/docs/plans/todo-github-actions-release-workflow.md +34 -0
- package/templates/default/docs/plans/todo-issue-spec-rename.md +24 -0
- package/templates/default/docs/plans/todo-phase4-marker-update.md +39 -0
- package/templates/default/docs/plans/todo-skill-creator-sync.md +23 -0
- package/templates/default/docs/plans/todo-skill-creator-upgrade.md +18 -0
- package/templates/default/docs/plans/typed-snuggling-parnas-agent-a6f6391.md +476 -0
- package/templates/default/docs/plans/typed-snuggling-parnas-agent-adb678b.md +144 -0
- package/templates/default/docs/plans/typed-snuggling-parnas.md +84 -0
- package/templates/default/docs/plans/velvety-chasing-spark.md +28 -0
- package/templates/default/docs/plans/warm-hopping-lighthouse-agent-a30aa4f.md +534 -0
- package/templates/default/docs/plans/warm-hopping-lighthouse-agent-a57a278.md +508 -0
- package/templates/default/docs/plans/warm-hopping-lighthouse-agent-a90b809.md +421 -0
- package/templates/default/docs/plans/warm-hopping-lighthouse.md +199 -0
- package/templates/default/docs/plans/wondrous-strolling-crystal-agent-a0615fc.md +215 -0
- package/templates/default/docs/plans/wondrous-strolling-crystal.md +182 -0
- package/templates/default/docs/plans/zesty-roaming-steele.md +74 -0
- package/templates/default/docs/verification-test.md +2 -0
- package/templates/default/gitignore +9 -1
- package/templates/default/package.json +6 -2
- package/templates/default/packages/admin-ui/package.json +1 -1
- package/templates/default/packages/server-core/tsconfig.json +6 -1
- package/templates/default/pnpm-lock.yaml +823 -57
- package/templates/default/scripts/ensure-serena.sh +75 -0
- package/templates/default/scripts/env-rotate-secrets.ts +66 -6
- package/templates/default/scripts/init-github.ts +363 -0
- package/templates/default/scripts/init.sh +11 -5
- package/templates/default/scripts/lib/worktree-config.ts +64 -0
- package/templates/default/scripts/setup-dev.ts +16 -1
- package/templates/default/scripts/stop-serena.sh +25 -0
- package/templates/default/scripts/worktree/dev.ts +2 -2
- package/templates/default/.claude/skills/create-einja-app-release/SKILL.md +0 -186
- package/templates/default/.claude/skills/dev-cli-release/SKILL.md +0 -173
- package/templates/default/.cursor/commands/spec-create.md +0 -227
- package/templates/default/.cursor/commands/task-exec.md +0 -287
- package/templates/default/.cursor/commands/update-docs-by-task-specs.md +0 -448
- /package/templates/default/scripts/{cli-template-update.ts → _cli-template-update.ts} +0 -0
- /package/templates/default/scripts/{template-update.ts → _template-update.ts} +0 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
# einja sync コマンド動作調査レポート
|
|
2
|
+
|
|
3
|
+
## 調査概要
|
|
4
|
+
|
|
5
|
+
作業ディレクトリ: `/Users/kzp/code/GitHub/einja-inc/einja-management-template`
|
|
6
|
+
|
|
7
|
+
別プロジェクトでinit/syncを実行した際に想定通り動作しない可能性がある処理を特定するため、`einja sync`コマンドの処理フローとファイルフィルタリング・マーカー処理の詳細を調査しました。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. sync コマンド処理フロー
|
|
12
|
+
|
|
13
|
+
### ファイルパス
|
|
14
|
+
`packages/cli/src/commands/sync.ts` (76-759行)
|
|
15
|
+
|
|
16
|
+
### 主要処理ステップ
|
|
17
|
+
|
|
18
|
+
1. **初期化・カテゴリ検証** (76-109行)
|
|
19
|
+
- `--only` オプションで指定されたカテゴリを `validateCategories()` で検証
|
|
20
|
+
- 無効なカテゴリがあればエラーメッセージを表示して終了
|
|
21
|
+
|
|
22
|
+
2. **マネージャークラスのインスタンス化** (109-117行)
|
|
23
|
+
```typescript
|
|
24
|
+
const metadataManager = new MetadataManager(cwd);
|
|
25
|
+
const fileFilter = new FileFilter(cwd, templateRoot);
|
|
26
|
+
const diffEngine = new DiffEngine();
|
|
27
|
+
const conflictReporter = new ConflictReporter();
|
|
28
|
+
const backupManager = new BackupManager(cwd);
|
|
29
|
+
const batchProcessor = new BatchProcessor(10);
|
|
30
|
+
const markerProcessor = new MarkerProcessor();
|
|
31
|
+
const projectPrivateSynchronizer = new ProjectPrivateSynchronizer();
|
|
32
|
+
const jsonProcessor = new JsonProcessor();
|
|
33
|
+
const orphanCleaner = new OrphanCleaner(cwd, fileFilter);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. **メタデータ読み込み** (119-123行)
|
|
37
|
+
- `.einja/sync-metadata.json` を読み込み
|
|
38
|
+
- ファイルハッシュ・最終同期日時等を取得
|
|
39
|
+
|
|
40
|
+
4. **同期対象ファイルスキャン** (125-133行)
|
|
41
|
+
- `FileFilter.scanSyncTargets({ categories })` で対象ファイルを列挙
|
|
42
|
+
- カテゴリフィルタが適用される
|
|
43
|
+
|
|
44
|
+
5. **差分計算(並列処理)** (135-160行)
|
|
45
|
+
- `batchProcessor.processBatch()` でファイルハッシュを計算
|
|
46
|
+
- メタデータと比較して変更があるファイルを抽出
|
|
47
|
+
|
|
48
|
+
6. **孤児検出** (162-165行)
|
|
49
|
+
- `orphanCleaner.detectOrphans()` でメタデータに存在するがテンプレートに存在しないファイルを検出
|
|
50
|
+
- `--only` で指定されたカテゴリのみ対象
|
|
51
|
+
|
|
52
|
+
7. **dry-runモード分岐** (196-345行)
|
|
53
|
+
- `--dry-run` 時はマージシミュレーションのみ実行
|
|
54
|
+
- コンフリクト検出結果を表示
|
|
55
|
+
|
|
56
|
+
8. **確認プロンプト** (347-368行)
|
|
57
|
+
- `--yes` 指定時はスキップ
|
|
58
|
+
- `--force` 時は特別な警告メッセージ
|
|
59
|
+
|
|
60
|
+
9. **バックアップ作成** (370-376行)
|
|
61
|
+
- `--backup=false` 以外は自動バックアップ
|
|
62
|
+
|
|
63
|
+
10. **ファイルマージ処理(並列計算→順次書き込み)** (378-589行)
|
|
64
|
+
- **マージ計算は並列実行**(`batchProcessor.processBatch()`)
|
|
65
|
+
- **ファイル書き込みは順次実行**(ファイルシステム競合を回避)
|
|
66
|
+
|
|
67
|
+
11. **孤児削除処理** (591-644行)
|
|
68
|
+
- `--clean` オプション指定時のみ実行
|
|
69
|
+
- 確認プロンプト(`--yes` でスキップ可能)
|
|
70
|
+
|
|
71
|
+
12. **メタデータ保存** (646行)
|
|
72
|
+
- 更新されたハッシュ・タイムスタンプを保存
|
|
73
|
+
|
|
74
|
+
13. **結果出力** (648-714行)
|
|
75
|
+
- `--json` オプション時は標準出力にJSON形式で出力
|
|
76
|
+
- 通常時は人間が読みやすい形式で表示
|
|
77
|
+
|
|
78
|
+
14. **依存関係チェック+インストール** (716-735行)
|
|
79
|
+
- `--skip-deps` 以外は `checkAndInstallDependencies()` を実行
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 2. ファイルフィルタ処理
|
|
84
|
+
|
|
85
|
+
### ファイルパス
|
|
86
|
+
`packages/cli/src/lib/sync/file-filter.ts` (28-275行)
|
|
87
|
+
|
|
88
|
+
### カテゴリマッピング(CATEGORY_MAPPING)
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const CATEGORY_MAPPING = {
|
|
92
|
+
agents: ".claude/agents/einja",
|
|
93
|
+
commands: ".claude/commands/einja",
|
|
94
|
+
docs: "docs/einja",
|
|
95
|
+
env: ".envrc", // 特殊処理: ファイル単位
|
|
96
|
+
hooks: ".claude/hooks/einja",
|
|
97
|
+
skills: ".claude/skills/einja",
|
|
98
|
+
tools: ".vscode/settings.json" // 特殊処理: ファイル単位
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### einja-プレフィックスフィルタリング(EINJA_PREFIX_CATEGORIES)
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const EINJA_PREFIX_CATEGORIES = ["agents", "commands", "skills", "hooks"];
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
これらのカテゴリでは `einja-*` で始まるディレクトリのみを対象にする。
|
|
109
|
+
|
|
110
|
+
### scanSyncTargets() の処理ロジック(41-134行)
|
|
111
|
+
|
|
112
|
+
1. `.gitignore` を読み込み(`loadGitignore()`)
|
|
113
|
+
2. 各カテゴリごとにスキャン:
|
|
114
|
+
- **env/toolsカテゴリ**: 特定ファイルのみ対象(`.envrc` / `.vscode/settings.json`)
|
|
115
|
+
- **einja-プレフィックス必須カテゴリ**: `{categoryPath}/einja-*/**/*` パターンでスキャン
|
|
116
|
+
- **その他**: `{categoryPath}/**/*` パターンでスキャン
|
|
117
|
+
3. 除外判定(`shouldExclude()`):
|
|
118
|
+
- `_` プレフィックスで始まるファイル
|
|
119
|
+
- `.gitignore` パターンに一致
|
|
120
|
+
- バイナリファイル(画像・動画・PDF・圧縮ファイル等)
|
|
121
|
+
- 追加の除外パターン(オプション)
|
|
122
|
+
|
|
123
|
+
### ⚠️ 潜在的問題点
|
|
124
|
+
|
|
125
|
+
#### 問題1: カテゴリパス不一致
|
|
126
|
+
別プロジェクトで以下のディレクトリ構造が異なる場合、スキャンに失敗する可能性がある:
|
|
127
|
+
- `.claude/agents/einja` → プロジェクトによっては `.claude/agents` のみの場合あり
|
|
128
|
+
- `docs/einja` → `docs/` 直下にドキュメントを配置している場合あり
|
|
129
|
+
|
|
130
|
+
#### 問題2: einja-プレフィックス制約
|
|
131
|
+
`agents`, `commands`, `skills`, `hooks` カテゴリでは `einja-` で始まらないディレクトリは **完全に無視される**。
|
|
132
|
+
- 例: `.claude/skills/my-custom-skill/` → スキャン対象外
|
|
133
|
+
|
|
134
|
+
#### 問題3: シンボリックリンクの扱い
|
|
135
|
+
`fs.pathExists()` で存在確認しているが、シンボリックリンクが切れている場合の処理が未定義。
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 3. マーカー処理
|
|
140
|
+
|
|
141
|
+
### ファイルパス
|
|
142
|
+
`packages/cli/src/lib/sync/marker-processor.ts` (11-458行)
|
|
143
|
+
|
|
144
|
+
### サポートされるマーカー種別
|
|
145
|
+
|
|
146
|
+
| マーカー | 用途 | ID属性 | sync時の動作 |
|
|
147
|
+
|---------|------|--------|-------------|
|
|
148
|
+
| `@einja:managed` | 共通ルール(常に最新を維持) | オプション | **常に上書き** |
|
|
149
|
+
| `@einja:project-private` | プロジェクト固有テンプレート | **必須** | 初回のみ追加、以降は保持 |
|
|
150
|
+
| `@einja:seed` (レガシー) | 旧project-private | オプション | 自動的に `@einja:project-private` にマイグレーション |
|
|
151
|
+
|
|
152
|
+
### マーカーフォーマット
|
|
153
|
+
|
|
154
|
+
**Markdown形式:**
|
|
155
|
+
```markdown
|
|
156
|
+
<!-- @einja:managed:start -->
|
|
157
|
+
<!-- @einja:managed:end -->
|
|
158
|
+
|
|
159
|
+
<!-- @einja:project-private:start id="xxx" -->
|
|
160
|
+
<!-- @einja:project-private:end -->
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**YAML/JSON形式(コメント):**
|
|
164
|
+
```yaml
|
|
165
|
+
# @einja:managed:start
|
|
166
|
+
# @einja:managed:end
|
|
167
|
+
|
|
168
|
+
# @einja:project-private:start id="xxx"
|
|
169
|
+
# @einja:project-private:end
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### マーカー検証ロジック(validateMarkers: 149-237行)
|
|
173
|
+
|
|
174
|
+
検証エラー種別:
|
|
175
|
+
- `nested`: マーカーの入れ子(managed内にproject-private等)
|
|
176
|
+
- `project_private_without_id`: project-privateマーカーにID属性がない
|
|
177
|
+
- `duplicate_id`: ID重複
|
|
178
|
+
- `unpaired_start`: 対応する `:end` がない
|
|
179
|
+
- `unpaired_end`: 対応する `:start` がない
|
|
180
|
+
|
|
181
|
+
### マーカーパース処理(parseMarkers: 60-141行)
|
|
182
|
+
|
|
183
|
+
1. ファイルを行単位で分割
|
|
184
|
+
2. マーカー開始/終了を検出してセクションに分離
|
|
185
|
+
3. 各セクションに以下の情報を付与:
|
|
186
|
+
- `type`: "managed" | "project-private" | "unmanaged"
|
|
187
|
+
- `startLine`, `endLine`: 行番号範囲
|
|
188
|
+
- `content`: セクション内容(マーカー行を含む)
|
|
189
|
+
- `id`: ID属性(あれば)
|
|
190
|
+
|
|
191
|
+
### レガシーマーカー自動マイグレーション(migrateLegacySeedMarkers: 453-457行)
|
|
192
|
+
|
|
193
|
+
sync.ts の 493-498行で自動実行:
|
|
194
|
+
```typescript
|
|
195
|
+
if (localContent.includes("@einja:seed:")) {
|
|
196
|
+
const migratedContent = markerProcessor.migrateLegacySeedMarkers(localContent);
|
|
197
|
+
await fs.writeFile(projectPath, migratedContent, "utf-8");
|
|
198
|
+
localContent = migratedContent;
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### ⚠️ 潜在的問題点
|
|
203
|
+
|
|
204
|
+
#### 問題4: マーカーバリデーション失敗時のフォールバック
|
|
205
|
+
マーカーが不正な場合、3方向マージにフォールバック(sync.ts: 639-652行)。
|
|
206
|
+
- エラーメッセージがユーザーに通知されない
|
|
207
|
+
- 意図しない上書きが発生する可能性
|
|
208
|
+
|
|
209
|
+
#### 問題5: ID属性の厳格性
|
|
210
|
+
`@einja:project-private` にID属性が必須だが、テンプレート側でIDが付与されていない場合、検証エラーとなる。
|
|
211
|
+
- 初期セットアップ時の混乱を招く可能性
|
|
212
|
+
|
|
213
|
+
#### 問題6: マーカーの正規表現パターン
|
|
214
|
+
以下のパターンはマーカーとして認識されない:
|
|
215
|
+
```markdown
|
|
216
|
+
<!--@einja:managed:start--> ← スペースなし(エラー)
|
|
217
|
+
<!-- @einja:managed:start--> ← 末尾のスペースなし(エラー)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 4. project-private-synchronizer
|
|
223
|
+
|
|
224
|
+
### ファイルパス
|
|
225
|
+
`packages/cli/src/lib/sync/project-private-synchronizer.ts` (9-125行)
|
|
226
|
+
|
|
227
|
+
### 主要メソッド
|
|
228
|
+
|
|
229
|
+
#### syncProjectPrivateSections(19-61行)
|
|
230
|
+
1. ローカルとテンプレートをパース
|
|
231
|
+
2. ローカルに存在する project-private の ID を収集
|
|
232
|
+
3. テンプレートの project-private で **ローカルに存在しない** ものを抽出
|
|
233
|
+
4. ローカルの末尾に追加
|
|
234
|
+
|
|
235
|
+
#### syncUnmarkedFile(70-79行)
|
|
236
|
+
マーカーなしファイルの処理:
|
|
237
|
+
- ローカルに存在しない → テンプレートをそのまま追加
|
|
238
|
+
- ローカルに存在する → 何もしない(null返却)
|
|
239
|
+
|
|
240
|
+
#### syncProjectPrivateOnlyFile(95-124行)
|
|
241
|
+
managedなしファイル(project-privateのみ)の処理:
|
|
242
|
+
1. project-privateセクションを抽出
|
|
243
|
+
2. 本文を3方向マージ
|
|
244
|
+
3. ローカルの project-private を保持、なければテンプレートのものをseed
|
|
245
|
+
|
|
246
|
+
### ⚠️ 潜在的問題点
|
|
247
|
+
|
|
248
|
+
#### 問題7: ID衝突時の動作
|
|
249
|
+
テンプレート側で新しいproject-privateセクションを追加したが、IDが既存のものと衝突した場合:
|
|
250
|
+
- `validateMarkers()` でエラーになる
|
|
251
|
+
- 3方向マージにフォールバックし、意図しない上書きの可能性
|
|
252
|
+
|
|
253
|
+
#### 問題8: project-privateセクションの削除
|
|
254
|
+
テンプレート側でproject-privateセクションを削除した場合、ローカル側には残り続ける。
|
|
255
|
+
- 意図的な削除なのか、リファクタリングなのか判別不能
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 5. orphan-cleaner
|
|
260
|
+
|
|
261
|
+
### ファイルパス
|
|
262
|
+
`packages/cli/src/lib/sync/orphan-cleaner.ts` (9-104行)
|
|
263
|
+
|
|
264
|
+
### detectOrphans(22-63行)
|
|
265
|
+
|
|
266
|
+
孤児検出ロジック:
|
|
267
|
+
1. メタデータに存在するファイルをループ
|
|
268
|
+
2. 現在のテンプレートファイルセットに存在しないものを孤児と判定
|
|
269
|
+
3. 以下のフィルタリングを適用:
|
|
270
|
+
- パストラバーサル防御(`..` や絶対パスを除外)
|
|
271
|
+
- カテゴリ判定(`fileFilter.getCategoryFromPath()`)
|
|
272
|
+
- `--only` オプションで指定されたカテゴリのみ
|
|
273
|
+
- カテゴリがnull(どのカテゴリにも属さない)の場合はスキップ
|
|
274
|
+
|
|
275
|
+
### ⚠️ 潜在的問題点
|
|
276
|
+
|
|
277
|
+
#### 問題9: カテゴリ推測の失敗
|
|
278
|
+
`getCategoryFromPath()` がnullを返すファイルは孤児として検出されない。
|
|
279
|
+
- カテゴリマッピングが変更された場合、古いファイルが残り続ける
|
|
280
|
+
|
|
281
|
+
#### 問題10: 孤児削除の確認プロンプト
|
|
282
|
+
`--clean` オプション時、確認プロンプトが表示されるが、`--yes` で自動承認可能。
|
|
283
|
+
- 誤削除のリスク(特にCI/CD環境で `--yes --clean` を使用する場合)
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 6. symlinks.json の処理
|
|
288
|
+
|
|
289
|
+
### ファイルパス
|
|
290
|
+
`packages/cli/src/lib/merger.ts` (128-229行)
|
|
291
|
+
|
|
292
|
+
### createSymlinks() の処理フロー
|
|
293
|
+
|
|
294
|
+
1. `symlinks.json` の存在確認(なければスキップ)
|
|
295
|
+
2. JSONパース・バージョンチェック
|
|
296
|
+
3. 各シンボリックリンクを作成:
|
|
297
|
+
```typescript
|
|
298
|
+
const linkPath = path.join(targetDir, link);
|
|
299
|
+
const absoluteTarget = path.join(targetDir, target);
|
|
300
|
+
const relativeTarget = path.relative(linkDir, absoluteTarget);
|
|
301
|
+
await fs.symlink(relativeTarget, linkPath);
|
|
302
|
+
```
|
|
303
|
+
4. エラーハンドリング:
|
|
304
|
+
- リンク先が存在しない → スキップ
|
|
305
|
+
- リンク元にディレクトリが存在 → エラー(手動削除を促す)
|
|
306
|
+
- Windows権限エラー(EPERM) → 実体ファイルコピーにフォールバック
|
|
307
|
+
|
|
308
|
+
### ⚠️ 潜在的問題点
|
|
309
|
+
|
|
310
|
+
#### 問題11: symlinks.json のパス計算
|
|
311
|
+
`symlinks.json` の `target` フィールドはルートからの相対パスとして扱われる。
|
|
312
|
+
- 例: `{ "link": "docs/einja/steering/commit-rules.md", "target": "docs/einja/steering/commit-rules.md" }`
|
|
313
|
+
- 別プロジェクトでディレクトリ構造が異なる場合、リンク切れが発生
|
|
314
|
+
|
|
315
|
+
#### 問題12: Windows環境での制約
|
|
316
|
+
Windows環境ではシンボリックリンク作成に管理者権限が必要。
|
|
317
|
+
- フォールバックで実体ファイルをコピーするが、以降の同期で更新されない
|
|
318
|
+
- ユーザーへの明確な警告が不足
|
|
319
|
+
|
|
320
|
+
#### 問題13: 既存ファイル/ディレクトリの扱い
|
|
321
|
+
リンク元にファイルがある場合は削除するが、ディレクトリがある場合はエラーで停止。
|
|
322
|
+
- 初回init時に衝突する可能性
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## 7. @einja:excluded マーカー
|
|
327
|
+
|
|
328
|
+
### 調査結果
|
|
329
|
+
コードベース内で `@einja:excluded` マーカーの処理実装は **見つかりませんでした**。
|
|
330
|
+
|
|
331
|
+
ただし、以下の箇所で使用されている形跡があります:
|
|
332
|
+
- `CLAUDE.md` (217-227行): `<!-- @einja:excluded:start -->` ... `<!-- @einja:excluded:end -->`
|
|
333
|
+
- MARKER_SPECIFICATION.md には記載なし
|
|
334
|
+
|
|
335
|
+
### ⚠️ 潜在的問題点
|
|
336
|
+
|
|
337
|
+
#### 問題14: @einja:excludedマーカーの未実装
|
|
338
|
+
`@einja:excluded` マーカーが CLAUDE.md で使用されているが、sync処理では認識・処理されていない。
|
|
339
|
+
- 意図としては「このセクションはテンプレート生成時に除外される」と推測されるが、実装がない
|
|
340
|
+
- テンプレート生成処理(`generateClaudeMd()`)でも処理されていない可能性
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 8. init コマンドとの関連
|
|
345
|
+
|
|
346
|
+
### ファイルパス
|
|
347
|
+
`packages/cli/src/commands/init.ts` (20-240行)
|
|
348
|
+
|
|
349
|
+
### init処理フロー
|
|
350
|
+
|
|
351
|
+
1. プリセット読み込み
|
|
352
|
+
2. 既存 `.claude` ディレクトリのバックアップ・削除
|
|
353
|
+
3. `.claude` ディレクトリ生成(`generateClaudeDirectory()`)
|
|
354
|
+
4. ドキュメントテンプレートコピー(`copyDocTemplates()`)
|
|
355
|
+
5. ステアリングドキュメントコピー(`copySteeringDocs()`)
|
|
356
|
+
6. CLAUDE.md生成(`generateClaudeMd()`)
|
|
357
|
+
7. **シンボリックリンク作成**(`createSymlinks()`)
|
|
358
|
+
8. `.mcp.json` セットアップ(`setupMcpConfig()`)
|
|
359
|
+
9. 依存関係チェック+インストール
|
|
360
|
+
|
|
361
|
+
### ⚠️ 潜在的問題点
|
|
362
|
+
|
|
363
|
+
#### 問題15: init後の初回sync
|
|
364
|
+
`einja init` で生成されたファイルには `.einja/sync-metadata.json` が存在しない。
|
|
365
|
+
- 初回 `einja sync` 実行時にメタデータがないため、全ファイルが「新規」扱いになる
|
|
366
|
+
- ハッシュ不一致による意図しない上書きの可能性
|
|
367
|
+
|
|
368
|
+
#### 問題16: シンボリックリンクのメタデータ管理
|
|
369
|
+
シンボリックリンクで配置されたファイルは `sync` 時にどう扱われるか不明確。
|
|
370
|
+
- メタデータにリンク先のハッシュが記録されるのか、リンク元のハッシュが記録されるのか
|
|
371
|
+
- リンク先が更新された場合、syncで検出されるのか
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 想定通り動作しない可能性がある処理(優先度順)
|
|
376
|
+
|
|
377
|
+
### 🔴 高優先度(必ず確認すべき)
|
|
378
|
+
|
|
379
|
+
1. **カテゴリパス不一致** (問題1)
|
|
380
|
+
- 別プロジェクトで `.claude/agents/einja` が存在しない場合、agents カテゴリが完全にスキップされる
|
|
381
|
+
- **影響**: 必要なエージェント設定が同期されない
|
|
382
|
+
|
|
383
|
+
2. **einja-プレフィックス制約** (問題2)
|
|
384
|
+
- カスタムスキル/エージェントが `einja-` プレフィックスなしの場合、スキャン対象外
|
|
385
|
+
- **影響**: プロジェクト固有の設定が同期されない
|
|
386
|
+
|
|
387
|
+
3. **@einja:excludedマーカーの未実装** (問題14)
|
|
388
|
+
- CLAUDE.md で使用されているが処理実装がない
|
|
389
|
+
- **影響**: 意図しないセクションがテンプレートに含まれる可能性
|
|
390
|
+
|
|
391
|
+
4. **init後の初回sync** (問題15)
|
|
392
|
+
- メタデータ未初期化のため、全ファイルが新規扱い
|
|
393
|
+
- **影響**: ローカル変更が上書きされる可能性
|
|
394
|
+
|
|
395
|
+
5. **symlinks.json のパス計算** (問題11)
|
|
396
|
+
- ディレクトリ構造が異なるプロジェクトでリンク切れ
|
|
397
|
+
- **影響**: 必要なドキュメントが参照できない
|
|
398
|
+
|
|
399
|
+
### 🟡 中優先度(状況によって影響あり)
|
|
400
|
+
|
|
401
|
+
6. **マーカーバリデーション失敗時のフォールバック** (問題4)
|
|
402
|
+
- エラー通知なしで3方向マージにフォールバック
|
|
403
|
+
- **影響**: 意図しない上書き、デバッグ困難
|
|
404
|
+
|
|
405
|
+
7. **ID属性の厳格性** (問題5)
|
|
406
|
+
- テンプレート側でID未付与の場合、検証エラー
|
|
407
|
+
- **影響**: 初期セットアップの混乱
|
|
408
|
+
|
|
409
|
+
8. **孤児検出のカテゴリ推測失敗** (問題9)
|
|
410
|
+
- カテゴリマッピング変更後、古いファイルが残り続ける
|
|
411
|
+
- **影響**: ディスク容量の浪費、混乱
|
|
412
|
+
|
|
413
|
+
9. **Windows環境でのシンボリックリンク制約** (問題12)
|
|
414
|
+
- 実体ファイルコピーにフォールバックするが、以降の同期で更新されない
|
|
415
|
+
- **影響**: ドキュメントが古いまま
|
|
416
|
+
|
|
417
|
+
### 🟢 低優先度(稀なケース)
|
|
418
|
+
|
|
419
|
+
10. **project-privateセクションのID衝突** (問題7)
|
|
420
|
+
11. **project-privateセクションの削除** (問題8)
|
|
421
|
+
12. **孤児削除の確認プロンプト** (問題10)
|
|
422
|
+
13. **シンボリックリンクのメタデータ管理** (問題16)
|
|
423
|
+
14. **マーカー正規表現パターン** (問題6)
|
|
424
|
+
15. **シンボリックリンクの扱い** (問題3)
|
|
425
|
+
16. **既存ファイル/ディレクトリの衝突** (問題13)
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## 推奨される対策
|
|
430
|
+
|
|
431
|
+
### 即座に対応すべき項目
|
|
432
|
+
|
|
433
|
+
1. **カテゴリパス検証機能の追加**
|
|
434
|
+
- `FileFilter.scanSyncTargets()` 実行前に、カテゴリパスの存在確認
|
|
435
|
+
- 存在しない場合は警告メッセージを表示
|
|
436
|
+
|
|
437
|
+
2. **@einja:excluded マーカーの実装確認**
|
|
438
|
+
- `generateClaudeMd()` でマーカー処理が実装されているか確認
|
|
439
|
+
- 未実装の場合は実装するか、マーカーを削除
|
|
440
|
+
|
|
441
|
+
3. **init コマンドでのメタデータ初期化**
|
|
442
|
+
- `einja init` 完了時に `.einja/sync-metadata.json` を初期生成
|
|
443
|
+
- ハッシュ値を記録して初回syncでの不一致を回避
|
|
444
|
+
|
|
445
|
+
4. **マーカーバリデーションエラーの通知**
|
|
446
|
+
- `validateMarkers()` でエラーが発生した場合、ユーザーに明示的に通知
|
|
447
|
+
- 3方向マージにフォールバックする前に警告を表示
|
|
448
|
+
|
|
449
|
+
### 中長期的に対応すべき項目
|
|
450
|
+
|
|
451
|
+
5. **einja-プレフィックス制約の緩和**
|
|
452
|
+
- カテゴリごとにプレフィックスフィルタの有無を設定可能にする
|
|
453
|
+
- プロジェクト固有のカテゴリ設定を `.einja/config.json` で管理
|
|
454
|
+
|
|
455
|
+
6. **Windows環境でのシンボリックリンク処理改善**
|
|
456
|
+
- 実体ファイルコピー後も `sync` で更新を検出する仕組み
|
|
457
|
+
- または、ディレクトリジャンクション(管理者権限不要)への切り替え
|
|
458
|
+
|
|
459
|
+
7. **孤児検出の改善**
|
|
460
|
+
- カテゴリ推測失敗時も検出できるよう、メタデータにカテゴリ情報を保存
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## まとめ
|
|
465
|
+
|
|
466
|
+
`einja sync` コマンドは堅牢なマーカーベースのマージシステムを持っていますが、以下の前提条件があります:
|
|
467
|
+
|
|
468
|
+
- テンプレートとプロジェクトのディレクトリ構造が一致している
|
|
469
|
+
- `einja-` プレフィックス規約に従っている
|
|
470
|
+
- マーカーが正しく設定されている
|
|
471
|
+
|
|
472
|
+
別プロジェクトで init/sync を実行する際は、これらの前提が満たされているか事前に確認する必要があります。
|
|
473
|
+
|
|
474
|
+
特に **カテゴリパス不一致**、**einja-プレフィックス制約**、**init後の初回sync** は高確率で問題になるため、優先的に対策することを推奨します。
|