@einja/dev-cli 0.1.40 → 0.1.44

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 (207) hide show
  1. package/README.md +89 -1
  2. package/dist/cli.js +1 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +71 -1
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/list.js.map +1 -1
  8. package/dist/commands/sync.d.ts.map +1 -1
  9. package/dist/commands/sync.js +187 -13
  10. package/dist/commands/sync.js.map +1 -1
  11. package/dist/commands/task-loop/lib/github-client.test.js.map +1 -1
  12. package/dist/commands/task-loop/lib/vibe-kanban-rest-client.js +2 -2
  13. package/dist/commands/task-loop/lib/vibe-kanban-rest-client.js.map +1 -1
  14. package/dist/lib/dependency-checker.d.ts.map +1 -1
  15. package/dist/lib/merger.d.ts +12 -0
  16. package/dist/lib/merger.d.ts.map +1 -1
  17. package/dist/lib/merger.js +28 -0
  18. package/dist/lib/merger.js.map +1 -1
  19. package/dist/lib/preset-update/cli-repo-detector.d.ts.map +1 -1
  20. package/dist/lib/preset-update/file-copier.d.ts.map +1 -1
  21. package/dist/lib/preset-update/file-copier.js +3 -3
  22. package/dist/lib/preset-update/file-copier.js.map +1 -1
  23. package/dist/lib/preset-update/preset-finder.d.ts.map +1 -1
  24. package/dist/lib/preset.d.ts.map +1 -1
  25. package/dist/lib/sync/category-validator.d.ts +1 -1
  26. package/dist/lib/sync/category-validator.d.ts.map +1 -1
  27. package/dist/lib/sync/category-validator.js +2 -1
  28. package/dist/lib/sync/category-validator.js.map +1 -1
  29. package/dist/lib/sync/category-validator.test.js +3 -1
  30. package/dist/lib/sync/category-validator.test.js.map +1 -1
  31. package/dist/lib/sync/conflict-reporter.d.ts.map +1 -1
  32. package/dist/lib/sync/diff-engine.d.ts.map +1 -1
  33. package/dist/lib/sync/file-filter.d.ts.map +1 -1
  34. package/dist/lib/sync/file-filter.js +1 -0
  35. package/dist/lib/sync/file-filter.js.map +1 -1
  36. package/dist/lib/sync/integration.test.js +255 -69
  37. package/dist/lib/sync/integration.test.js.map +1 -1
  38. package/dist/lib/sync/json-processor.d.ts +4 -4
  39. package/dist/lib/sync/json-processor.d.ts.map +1 -1
  40. package/dist/lib/sync/json-processor.js +11 -11
  41. package/dist/lib/sync/json-processor.js.map +1 -1
  42. package/dist/lib/sync/marker-processor.d.ts +60 -8
  43. package/dist/lib/sync/marker-processor.d.ts.map +1 -1
  44. package/dist/lib/sync/marker-processor.js +117 -26
  45. package/dist/lib/sync/marker-processor.js.map +1 -1
  46. package/dist/lib/sync/marker-processor.test.js +261 -40
  47. package/dist/lib/sync/marker-processor.test.js.map +1 -1
  48. package/dist/lib/sync/metadata-manager.d.ts +4 -0
  49. package/dist/lib/sync/metadata-manager.d.ts.map +1 -1
  50. package/dist/lib/sync/metadata-manager.js +15 -0
  51. package/dist/lib/sync/metadata-manager.js.map +1 -1
  52. package/dist/lib/sync/metadata-manager.test.js +69 -0
  53. package/dist/lib/sync/metadata-manager.test.js.map +1 -1
  54. package/dist/lib/sync/orphan-cleaner.d.ts +29 -0
  55. package/dist/lib/sync/orphan-cleaner.d.ts.map +1 -0
  56. package/dist/lib/sync/orphan-cleaner.js +80 -0
  57. package/dist/lib/sync/orphan-cleaner.js.map +1 -0
  58. package/dist/lib/sync/orphan-cleaner.test.d.ts +2 -0
  59. package/dist/lib/sync/orphan-cleaner.test.d.ts.map +1 -0
  60. package/dist/lib/sync/orphan-cleaner.test.js +169 -0
  61. package/dist/lib/sync/orphan-cleaner.test.js.map +1 -0
  62. package/dist/lib/sync/project-private-synchronizer.d.ts +52 -0
  63. package/dist/lib/sync/project-private-synchronizer.d.ts.map +1 -0
  64. package/dist/lib/sync/project-private-synchronizer.js +110 -0
  65. package/dist/lib/sync/project-private-synchronizer.js.map +1 -0
  66. package/dist/lib/sync/project-private-synchronizer.test.d.ts +2 -0
  67. package/dist/lib/sync/project-private-synchronizer.test.d.ts.map +1 -0
  68. package/dist/lib/sync/project-private-synchronizer.test.js +348 -0
  69. package/dist/lib/sync/project-private-synchronizer.test.js.map +1 -0
  70. package/dist/types/index.d.ts +1 -0
  71. package/dist/types/index.d.ts.map +1 -1
  72. package/dist/types/sync.d.ts +36 -6
  73. package/dist/types/sync.d.ts.map +1 -1
  74. package/dist/types/sync.js +2 -2
  75. package/dist/types/sync.js.map +1 -1
  76. package/package.json +5 -4
  77. package/presets/default/.claude/agents/einja/Explore.md +140 -0
  78. package/presets/default/.claude/agents/einja/backend-architect.md +21 -1
  79. package/presets/default/.claude/agents/einja/codex-agent.md +5 -1
  80. package/presets/default/.claude/agents/einja/design-engineer.md +5 -1
  81. package/presets/default/.claude/agents/einja/docs/docs-updater.md +7 -93
  82. package/presets/default/.claude/agents/einja/frontend-architect.md +21 -1
  83. package/presets/default/.claude/agents/einja/frontend-coder.md +5 -1
  84. package/presets/default/.claude/agents/einja/{specs/spec-design-generator.md → issue-specs/design-generator.md} +16 -8
  85. package/presets/default/.claude/agents/einja/{specs/spec-qa-generator.md → issue-specs/qa-generator.md} +10 -4
  86. package/presets/default/.claude/agents/einja/{specs/spec-requirements-generator.md → issue-specs/requirements-generator.md} +9 -6
  87. package/presets/default/.claude/agents/einja/{specs/spec-tasks-generator.md → issue-specs/tasks-generator.md} +19 -16
  88. package/presets/default/.claude/agents/einja/{specs/spec-tasks-validator.md → issue-specs/tasks-validator.md} +13 -9
  89. package/presets/default/.claude/agents/einja/issue-specs/ui-design-generator.md +114 -0
  90. package/presets/default/.claude/agents/einja/task/task-executer.md +64 -116
  91. package/presets/default/.claude/agents/einja/task/task-modification-analyzer.md +6 -2
  92. package/presets/default/.claude/agents/einja/task/task-qa.md +7 -3
  93. package/presets/default/.claude/agents/einja/task/task-reviewer.md +17 -1
  94. package/presets/default/.claude/commands/einja/einja-sync.md +124 -45
  95. package/presets/default/.claude/commands/einja/frontend-implement.md +3 -1
  96. package/presets/default/.claude/commands/einja/issue-exec.md +413 -0
  97. package/presets/default/.claude/commands/einja/start-dev.md +4 -0
  98. package/presets/default/.claude/commands/einja/sync-cursor-commands.md +10 -6
  99. package/presets/default/.claude/commands/einja/{update-docs-by-task-specs.md → update-docs-by-issue-specs.md} +61 -57
  100. package/presets/default/.claude/hooks/einja/plan-mode-skill-loader.sh +27 -0
  101. package/presets/default/.claude/settings.json +29 -5
  102. package/presets/default/.claude/skills/{einja-general-context-loader → _einja-general-context-loader}/SKILL.md +6 -2
  103. package/presets/default/.claude/skills/{einja-output-format → _einja-output-format}/SKILL.md +5 -1
  104. package/presets/default/.claude/skills/_einja-project-overview/SKILL.md +29 -0
  105. package/presets/default/.claude/skills/{einja-spec-context-loader → _einja-spec-context-loader}/SKILL.md +9 -5
  106. package/presets/default/.claude/skills/einja-coding-standards/references/testing-strategy.md +899 -0
  107. package/presets/default/.claude/skills/einja-conflict-resolver/SKILL.md +5 -1
  108. package/presets/default/.claude/skills/einja-create-pr/SKILL.md +138 -0
  109. package/presets/default/.claude/skills/einja-infra-maintenance/SKILL.md +779 -0
  110. package/presets/default/.claude/{commands/einja/spec-create.md → skills/einja-issue-spec-create/SKILL.md} +60 -23
  111. package/presets/default/.claude/skills/einja-issue-spec-generator/SKILL.md +105 -0
  112. package/presets/default/.claude/skills/einja-issue-spec-generator/references/format-rules.md +35 -0
  113. package/presets/default/.claude/skills/einja-issue-spec-validator/SKILL.md +130 -0
  114. package/presets/default/.claude/skills/einja-issue-spec-validator/references/validation-rules.md +52 -0
  115. package/presets/default/.claude/skills/einja-npm-release/SKILL.md +242 -0
  116. package/presets/default/.claude/skills/einja-skill-creator/SKILL.md +311 -263
  117. package/presets/default/.claude/skills/einja-skill-creator/agents/analyzer.md +274 -0
  118. package/presets/default/.claude/skills/einja-skill-creator/agents/comparator.md +202 -0
  119. package/presets/default/.claude/skills/einja-skill-creator/agents/grader.md +195 -0
  120. package/presets/default/.claude/skills/einja-skill-creator/assets/eval_review.html +146 -0
  121. package/presets/default/.claude/skills/einja-skill-creator/eval-viewer/generate_review.py +471 -0
  122. package/presets/default/.claude/skills/einja-skill-creator/eval-viewer/viewer.html +1325 -0
  123. package/presets/default/.claude/skills/einja-skill-creator/references/schemas.md +430 -0
  124. package/presets/default/.claude/skills/einja-skill-creator/scripts/aggregate_benchmark.py +401 -0
  125. package/presets/default/.claude/skills/einja-skill-creator/scripts/compare_runs.py +154 -0
  126. package/presets/default/.claude/skills/einja-skill-creator/scripts/generate_report.py +272 -0
  127. package/presets/default/.claude/skills/einja-skill-creator/scripts/improve_description.py +247 -0
  128. package/presets/default/.claude/skills/einja-skill-creator/scripts/init_skill.py +13 -19
  129. package/presets/default/.claude/skills/einja-skill-creator/scripts/package_skill.py +36 -7
  130. package/presets/default/.claude/skills/einja-skill-creator/scripts/run_eval.py +310 -0
  131. package/presets/default/.claude/skills/einja-skill-creator/scripts/run_loop.py +375 -0
  132. package/presets/default/.claude/skills/einja-skill-creator/scripts/utils.py +48 -0
  133. package/presets/default/.claude/skills/einja-skill-first/SKILL.md +265 -0
  134. package/presets/default/.claude/skills/einja-subagent-question-protocol/SKILL.md +98 -0
  135. package/presets/default/.claude/skills/einja-task-commit/SKILL.md +11 -7
  136. package/presets/default/.claude/{commands/einja/task-exec.md → skills/einja-task-exec/SKILL.md} +106 -89
  137. package/presets/default/.claude/skills/einja-task-qa/SKILL.md +8 -4
  138. package/presets/default/.claude/skills/einja-task-qa/references/troubleshooting.md +1 -1
  139. package/presets/default/.claude/skills/einja-task-qa/references/usage-patterns.md +2 -2
  140. package/presets/default/.claude/skills/einja-team-exec/SKILL.md +165 -0
  141. package/presets/default/.envrc +5 -0
  142. package/presets/default/.mcp.json +2 -12
  143. package/presets/default/CLAUDE.md.template +45 -8
  144. package/presets/default/docs/einja/example/specs/issues/issue999-example-task/tasks.md +1 -1
  145. package/presets/default/docs/einja/instructions/deployment-setup.md +4 -9
  146. package/presets/default/docs/einja/instructions/environment-setup.md +3 -8
  147. package/presets/default/docs/einja/instructions/issue-exec-workflow.md +276 -0
  148. package/presets/default/docs/einja/instructions/local-server-environment-and-worktree.md +71 -9
  149. package/presets/default/docs/einja/instructions/neon-cli-reference.md +3 -8
  150. package/presets/default/docs/einja/instructions/setup-flow.md +279 -0
  151. package/presets/default/docs/einja/instructions/task-execute.md +63 -68
  152. package/presets/default/docs/einja/instructions/vercel-cli-reference.md +17 -10
  153. package/presets/default/docs/einja/steering/README.md +11 -11
  154. package/presets/default/docs/einja/steering/acceptance-criteria-and-qa-guide.md +4 -9
  155. package/presets/default/docs/einja/steering/architecture.md +3 -8
  156. package/presets/default/docs/einja/steering/branch-strategy.md +63 -70
  157. package/presets/default/docs/einja/steering/commit-rules.md +3 -8
  158. package/presets/default/docs/einja/steering/db-schema-design.md +3 -8
  159. package/presets/default/docs/einja/steering/development/api-development.md +3 -8
  160. package/presets/default/docs/einja/steering/development/backend-architecture.md +3 -8
  161. package/presets/default/docs/einja/steering/development/coding-standards.md +723 -0
  162. package/presets/default/docs/einja/steering/development/component-design.md +502 -0
  163. package/presets/default/docs/einja/steering/development/database-guidelines.md +2 -2
  164. package/presets/default/docs/einja/steering/development/frontend-development.md +3 -8
  165. package/presets/default/docs/einja/steering/development/playwright-guidelines.md +59 -0
  166. package/presets/default/docs/einja/steering/development/review-guidelines.md +3 -8
  167. package/presets/default/docs/einja/steering/development/testing-strategy.md +3 -8
  168. package/presets/default/docs/einja/steering/development-workflow.md +155 -140
  169. package/presets/default/docs/einja/steering/infrastructure/deployment.md +156 -55
  170. package/presets/default/docs/einja/steering/infrastructure/environment-variables.md +4 -8
  171. package/presets/default/docs/einja/steering/product.md +3 -8
  172. package/presets/default/docs/einja/steering/task-management.md +22 -110
  173. package/presets/default/scripts/ensure-serena.sh +75 -0
  174. package/presets/default/scripts/env-rotate-secrets.ts +396 -0
  175. package/presets/default/scripts/env-show.ts +130 -0
  176. package/presets/default/scripts/env.ts +479 -0
  177. package/presets/default/scripts/init-github.ts +363 -0
  178. package/presets/default/scripts/init.sh +98 -0
  179. package/presets/default/scripts/lib/env-common.ts +108 -0
  180. package/presets/default/scripts/lib/worktree-config.ts +64 -0
  181. package/presets/default/scripts/setup-dev.ts +655 -0
  182. package/presets/default/scripts/stop-serena.sh +25 -0
  183. package/presets/default/scripts/worktree/dev.ts +872 -0
  184. package/dist/lib/sync/seed-synchronizer.d.ts +0 -27
  185. package/dist/lib/sync/seed-synchronizer.d.ts.map +0 -1
  186. package/dist/lib/sync/seed-synchronizer.js +0 -72
  187. package/dist/lib/sync/seed-synchronizer.js.map +0 -1
  188. package/dist/lib/sync/seed-synchronizer.test.d.ts +0 -2
  189. package/dist/lib/sync/seed-synchronizer.test.d.ts.map +0 -1
  190. package/dist/lib/sync/seed-synchronizer.test.js +0 -147
  191. package/dist/lib/sync/seed-synchronizer.test.js.map +0 -1
  192. package/presets/default/.claude/agents/einja/git/conflict-resolver.md +0 -148
  193. package/presets/default/.claude/hooks/einja/validate-git-commit.sh +0 -239
  194. package/presets/default/.claude/skills/einja-api-development/SKILL.md +0 -14
  195. package/presets/default/.claude/skills/einja-backend-architecture/SKILL.md +0 -18
  196. package/presets/default/.claude/skills/einja-coding-standards/SKILL.md +0 -132
  197. package/presets/default/.claude/skills/einja-coding-standards/references/import-conventions.md +0 -69
  198. package/presets/default/.claude/skills/einja-coding-standards/references/naming-conventions.md +0 -107
  199. package/presets/default/.claude/skills/einja-coding-standards/references/prohibited-patterns.md +0 -169
  200. package/presets/default/.claude/skills/einja-coding-standards/references/typescript-rules.md +0 -247
  201. package/presets/default/.claude/skills/einja-component-design/SKILL.md +0 -109
  202. package/presets/default/.claude/skills/einja-component-design/references/directory-structure.md +0 -117
  203. package/presets/default/.claude/skills/einja-component-design/references/props-patterns.md +0 -159
  204. package/presets/default/.claude/skills/einja-component-design/references/styling-guide.md +0 -122
  205. package/presets/default/.claude/skills/einja-frontend-development/SKILL.md +0 -14
  206. package/presets/default/.claude/skills/einja-project-overview/SKILL.md +0 -35
  207. package/presets/default/docs/einja/instructions/task-vibe-kanban-loop.md +0 -565
@@ -134,6 +134,7 @@ graph LR
134
134
  ReleaseCLI[release-cli.yml]
135
135
  ReleaseApp[release-create-einja-app.yml]
136
136
  Claude[claude.yml]
137
+ ChangesetStatus[changeset-status.yml]
137
138
  end
138
139
 
139
140
  subgraph "Composite Actions"
@@ -155,13 +156,14 @@ graph LR
155
156
 
156
157
  | ワークフロー | ファイル | トリガー | 用途 |
157
158
  |------------|---------|---------|------|
158
- | **Deploy Stable** | `deploy-stable-branches.yml` | push to main/develop/staging | CI → 本番・開発・ステージング環境デプロイ |
159
+ | **Deploy Stable** | `deploy-stable-branches.yml` | push to main/develop/staging | CI → 動的マトリクス → 変更アプリのみデプロイ(`--env`実行時注入) |
159
160
  | **PR Preview** | `deploy-pr-preview.yml` | PR opened/sync/closed | CI → Neonブランチ作成 → プレビューデプロイ |
160
161
  | **PR Close Cleanup** | `cleanup-pr-preview-on-close.yml` | PR closed | Neonブランチの即座削除(PR close時) |
161
162
  | **Cleanup DB** | `cleanup-pr-preview-db.yml` | 毎日00:00 UTC / 手動 | 孤立したNeonブランチ削除 |
162
163
  | **Release CLI** | `release-cli.yml` | tag `cli-v*` / 手動 | @einja/dev-cli をNPM公開 |
163
164
  | **Release App** | `release-create-einja-app.yml` | tag `create-einja-app-v*` / 手動 | create-einja-app をNPM公開 |
164
165
  | **Claude** | `claude.yml` | @claude メンション | Claude Code実行 |
166
+ | **Changeset Status** | `changeset-status.yml` | PR to main/staging | PR上にchangesetの有無を表示 |
165
167
 
166
168
  ### Composite Actions(2層構造)
167
169
 
@@ -185,8 +187,7 @@ flowchart TB
185
187
  end
186
188
 
187
189
  subgraph "migrate/action.yml"
188
- M1[setup action 呼び出し] --> M2[pnpm generate]
189
- M2 --> M3[db:migrate:deploy]
190
+ M1[setup action 呼び出し] --> M3[db:migrate:deploy]
190
191
  M3 --> M4{run-seed?}
191
192
  M4 -->|true| M5[db:seed]
192
193
  M4 -->|false| M6[完了]
@@ -201,7 +202,7 @@ flowchart TB
201
202
  |--------|---------|------|-----------|
202
203
  | **Setup** | `actions/setup/action.yml` | pnpm + Node.js + install | ci action, migrate action, cleanup |
203
204
  | **CI** | `actions/ci/action.yml` | setup → generate → [migrate] → typecheck → lint → test | deploy-stable-branches, deploy-pr-preview |
204
- | **Migrate** | `actions/migrate/action.yml` | setup → generate → migrate → seed (optional) | deploy-stable-branches |
205
+ | **Migrate** | `actions/migrate/action.yml` | setup → migrate → seed (optional) | deploy-stable-branches |
205
206
  | **Neon Export Env** | `actions/neon-export-env/action.yml` | .env.previewからNeon環境変数をエクスポート | deploy-pr-preview, cleanup-pr-preview-on-close |
206
207
 
207
208
  ### 実行マトリクス
@@ -258,9 +259,8 @@ sequenceDiagram
258
259
  rect rgb(240, 255, 240)
259
260
  Note over Actions,Vercel: Vercel デプロイ
260
261
  Actions->>Vercel: vercel pull
261
- Actions->>Vercel: 環境変数同期 (encrypted-only)
262
262
  Actions->>Vercel: vercel build (DATABASE_URL=pooled)
263
- Actions->>Vercel: vercel deploy --prebuilt
263
+ Actions->>Vercel: vercel deploy --prebuilt --env(全encrypted変数を実行時注入)
264
264
  Vercel-->>Actions: Preview URL
265
265
  end
266
266
 
@@ -308,10 +308,12 @@ sequenceDiagram
308
308
  rect rgb(240, 255, 240)
309
309
  Note over Actions,Vercel: Vercel デプロイ
310
310
  Actions->>Vercel: vercel pull
311
- Actions->>Vercel: 環境変数同期 (encrypted-only)
312
- Actions->>Vercel: vercel pull (Re-pull: 同期後の最新化)
311
+ alt mainブランチのみ
312
+ Actions->>Vercel: 環境変数同期 (encrypted-only, vercel env add)
313
+ Actions->>Vercel: vercel pull (Re-pull: 同期後の最新化)
314
+ end
313
315
  Actions->>Vercel: vercel build [--prod]
314
- Actions->>Vercel: vercel deploy --prebuilt [--prod]
316
+ Actions->>Vercel: vercel deploy --prebuilt --env [--prod](全encrypted変数を実行時注入)
315
317
  Vercel-->>Actions: Deploy URL
316
318
  end
317
319
 
@@ -383,15 +385,15 @@ sequenceDiagram
383
385
  ```mermaid
384
386
  flowchart TD
385
387
  A[git push main] --> B[deploy-stable-branches.yml]
386
- B --> C[CI Checks]
387
- C --> D{成功?}
388
+ B --> C[CI Checks + 変更検知]
389
+ C --> D{成功 & 変更あり?}
388
390
  D -->|Yes| E[dotenvx復号化]
389
- D -->|No| X[失敗通知]
391
+ D -->|No| X[スキップ]
390
392
  E --> F[Vercel Pull]
391
- F --> G[環境変数同期]
393
+ F --> G[環境変数同期 vercel env add]
392
394
  G --> H[DB Migrate]
393
395
  H --> I[Vercel Build]
394
- I --> J[Vercel Deploy --prod]
396
+ I --> J[Vercel Deploy --prod --env]
395
397
  J --> K[完了]
396
398
 
397
399
  style A fill:#4CAF50
@@ -413,19 +415,18 @@ flowchart TD
413
415
  ```mermaid
414
416
  flowchart TD
415
417
  A[git push develop] --> B[deploy-stable-branches.yml]
416
- B --> C[CI Checks]
417
- C --> D{成功?}
418
+ B --> C[CI Checks + 変更検知]
419
+ C --> D{成功 & 変更あり?}
418
420
  D -->|Yes| E[dotenvx復号化]
419
- D -->|No| X[失敗通知]
421
+ D -->|No| X[スキップ]
420
422
  E --> F[Vercel Pull]
421
- F --> G[環境変数同期]
422
- G --> H[Vercel Build]
423
- H --> I[Vercel Deploy]
424
- I --> J[Alias設定]
425
- J --> K[完了]
423
+ F --> G[Vercel Build]
424
+ G --> H[Vercel Deploy --env]
425
+ H --> I[Alias設定]
426
+ I --> J[完了]
426
427
 
427
428
  style A fill:#2196F3
428
- style K fill:#2196F3
429
+ style J fill:#2196F3
429
430
  ```
430
431
 
431
432
  **設定**:
@@ -434,7 +435,7 @@ flowchart TD
434
435
  - 復号鍵: `DOTENV_PRIVATE_KEY_DEVELOP`
435
436
  - DBマイグレーション: ❌(PR PreviewのNeonブランチで自動同期)
436
437
  - DBシード: ❌
437
- - Alias: `secrets.VERCEL_DEV_DOMAIN`
438
+ - Alias: `.env.develop` 内の `VERCEL_ALIAS_DOMAIN_WEB` / `VERCEL_ALIAS_DOMAIN_ADMIN`(dotenvx復号で取得)
438
439
 
439
440
  ---
440
441
 
@@ -443,20 +444,19 @@ flowchart TD
443
444
  ```mermaid
444
445
  flowchart TD
445
446
  A[git push staging] --> B[deploy-stable-branches.yml]
446
- B --> C[CI Checks]
447
- C --> D{成功?}
447
+ B --> C[CI Checks + 変更検知]
448
+ C --> D{成功 & 変更あり?}
448
449
  D -->|Yes| E[dotenvx復号化]
449
- D -->|No| X[失敗通知]
450
+ D -->|No| X[スキップ]
450
451
  E --> F[Vercel Pull]
451
- F --> G[環境変数同期]
452
- G --> H[DB Migrate]
453
- H --> I[Vercel Build]
454
- I --> J[Vercel Deploy]
455
- J --> K[Alias設定]
456
- K --> L[完了]
452
+ F --> G[DB Migrate]
453
+ G --> H[Vercel Build]
454
+ H --> I[Vercel Deploy --env]
455
+ I --> J[Alias設定]
456
+ J --> K[完了]
457
457
 
458
458
  style A fill:#FF9800
459
- style L fill:#FF9800
459
+ style K fill:#FF9800
460
460
  ```
461
461
 
462
462
  **設定**:
@@ -465,7 +465,7 @@ flowchart TD
465
465
  - 復号鍵: `DOTENV_PRIVATE_KEY_STAGING`
466
466
  - DBマイグレーション: ✅
467
467
  - DBシード: ❌(既存データ保持)
468
- - Alias: `secrets.VERCEL_STG_DOMAIN`
468
+ - Alias: `.env.staging` 内の `VERCEL_ALIAS_DOMAIN_WEB` / `VERCEL_ALIAS_DOMAIN_ADMIN`(dotenvx復号で取得)
469
469
 
470
470
  ---
471
471
 
@@ -506,12 +506,12 @@ flowchart TD
506
506
 
507
507
  > **⚠️ 同時PR運用時の注意**
508
508
  >
509
- > テンプレートでは`vercel deploy --env DATABASE_URL=...`でデプロイ単位で
510
- > DATABASE_URLを注入しています。これにより、同時に複数のPRがプレビュー
511
- > デプロイされても、それぞれのPRが固有のNeonブランチDBを参照します。
509
+ > テンプレートでは`vercel deploy --env KEY=VALUE`でデプロイ単位で
510
+ > 全encrypted環境変数(DATABASE_URL含む)を実行時注入しています。
511
+ > これにより、同時に複数のPRがプレビューデプロイされても、
512
+ > それぞれのPRが固有のNeonブランチDBを参照し、環境変数の競合が発生しません。
512
513
  >
513
- > もし`vercel env add DATABASE_URL`方式を使用すると、Vercel Projectの
514
- > preview環境変数が上書きされ、同時PRで競合するリスクがあります。
514
+ > PR環境では`vercel env add`は使用しません(並行PR間の競合を防ぐため)。
515
515
 
516
516
  ---
517
517
 
@@ -520,20 +520,21 @@ flowchart TD
520
520
  | 環境 | ブランチ | Vercel環境 | DBマイグ | シード | Alias | 暗号化ファイル | 復号鍵 |
521
521
  |------|---------|-----------|:-------:|:-----:|:-----:|--------------|--------|
522
522
  | Production | main | production | ✅ | ❌ | ❌ | `.env.production` | `DOTENV_PRIVATE_KEY_PRODUCTION` |
523
- | Develop | develop | preview | ❌ | ❌ | ✅ | `.env.develop` | `DOTENV_PRIVATE_KEY_DEVELOP` |
524
- | Staging | staging | preview | ✅ | ❌ | ✅ | `.env.staging` | `DOTENV_PRIVATE_KEY_STAGING` |
523
+ | Develop | develop | preview | ❌ | ❌ | ✅ `VERCEL_ALIAS_DOMAIN_*` | `.env.develop` | `DOTENV_PRIVATE_KEY_DEVELOP` |
524
+ | Staging | staging | preview | ✅ | ❌ | ✅ `VERCEL_ALIAS_DOMAIN_*` | `.env.staging` | `DOTENV_PRIVATE_KEY_STAGING` |
525
525
  | PR Preview | feature/* | preview | ✅ | ✅ | ❌ | `.env.preview` | `DOTENV_PRIVATE_KEY_PREVIEW` |
526
526
 
527
527
  ### Vercel環境変数の自動同期
528
528
 
529
529
  ワークフローは **encrypted-only方式** で同期対象を制御:
530
530
 
531
- | ワークフロー | 同期対象 | 除外 | 説明 |
532
- |------------|---------|------|------|
533
- | PR Preview | `.env.preview` 内の `encrypted:` キー | `NEON_*`, `DATABASE_*` | dotenvxで管理しているもの = Vercelに同期すべきもの |
534
- | Stable Branches | `.env.{env}` 内の `encrypted:` キー | なし | dotenvxで管理している全キーを同期 |
531
+ | ワークフロー | 方式 | 同期対象 | 除外 | 説明 |
532
+ |------------|------|---------|------|------|
533
+ | PR Preview | `--env`実行時注入 | `.env.preview` 内の `encrypted:` キー | `NEON_*`, `DOTENV_PUBLIC_KEY_*` | `vercel env add`は使用しない(並行PR競合防止) |
534
+ | Stable (main) | `vercel env add` + `--env`実行時注入 | `.env.production` 内の `encrypted:` キー | `NEON_*` | mainのみVercel環境変数ストアに同期 |
535
+ | Stable (develop/staging) | `--env`実行時注入 | `.env.{env}` 内の `encrypted:` キー | `NEON_*`, `VERCEL_ALIAS_DOMAIN_*`, `DOTENV_PUBLIC_KEY_*` | `vercel env add`は使用しない |
535
536
 
536
- **設計意図**: dotenvxの暗号化ファイル内の `encrypted:` を含む行のキー名のみを対象とし、「dotenvxで管理 = Vercelに同期」の意図を明確にする。ブラックリスト方式(全env走査)ではシステム変数混入や新変数追加時の漏れリスクがあるため廃止。
537
+ **設計意図**: `vercel env add`によるVercel環境変数ストアへの書き込みはmainブランチのみに限定。develop/staging/PRは`vercel deploy --env`による実行時注入で環境変数を渡し、並行デプロイ間の競合を防止する。
537
538
 
538
539
  ---
539
540
 
@@ -680,6 +681,111 @@ sequenceDiagram
680
681
 
681
682
  ---
682
683
 
684
+ ## 8. リリース管理
685
+
686
+ ### GitHub Release / PreRelease 自動作成フロー
687
+
688
+ ```mermaid
689
+ flowchart LR
690
+ subgraph staging
691
+ S1[staging push] --> S2[CI + Deploy]
692
+ S2 --> S3[PreRelease作成<br/>v0.2.0-rc.42]
693
+ end
694
+
695
+ subgraph main
696
+ M1[main push] --> M2[CI]
697
+ M2 --> M3[⚠️承認待ち]
698
+ M3 --> M4[Migrate + Deploy]
699
+ M4 --> M5[changeset version]
700
+ M5 --> M6[Release作成<br/>v0.2.0]
701
+ end
702
+
703
+ staging -->|昇格PR| main
704
+ ```
705
+
706
+ | 環境 | リリース種別 | タグ形式 | changeset消費 | 承認 |
707
+ |------|------------|---------|:------------:|:----:|
708
+ | staging | PreRelease | `v{version}-rc.{run_number}` | ❌ | 不要 |
709
+ | production | Release | `v{version}` | ✅ | 1名必要 |
710
+
711
+ ### ワークフロー内リリースジョブ
712
+
713
+ `deploy-stable-branches.yml` 内に統合:
714
+
715
+ | ジョブ | トリガー | 処理内容 |
716
+ |--------|---------|---------|
717
+ | `release-staging` | staging デプロイ成功後 | RCタグ作成 → GitHub PreRelease作成 |
718
+ | `release-production` | production デプロイ成功後 | changeset version → バージョンバンプ → タグ作成 → GitHub Release作成 |
719
+
720
+ ### NPMリリースとの棲み分け
721
+
722
+ | タグパターン | 用途 | 生成元 |
723
+ |-------------|------|--------|
724
+ | `v1.2.0` | アプリ Stable Release | deploy-stable-branches.yml |
725
+ | `v1.2.0-rc.42` | アプリ PreRelease | deploy-stable-branches.yml |
726
+ | `cli-v0.1.41` | @einja/dev-cli | 手動タグ(既存運用) |
727
+ | `create-einja-app-v0.3.2` | create-einja-app | 手動タグ(既存運用) |
728
+
729
+ ---
730
+
731
+ ## 9. バージョニング戦略
732
+
733
+ ### changesets
734
+
735
+ [changesets](https://github.com/changesets/changesets) を使用してセマンティックバージョニングを管理。
736
+
737
+ | 変更種別 | changeset指定 | バージョン変更例 | 使用シーン |
738
+ |---------|--------------|----------------|----------|
739
+ | 破壊的変更 | `major` | `0.1.0` → `1.0.0` | API仕様変更、DB破壊的マイグレーション |
740
+ | 新機能追加 | `minor` | `0.1.0` → `0.2.0` | 新画面、新API追加 |
741
+ | バグ修正 | `patch` | `0.1.0` → `0.1.1` | 不具合修正、パフォーマンス改善 |
742
+
743
+ ### changeset消費タイミング
744
+
745
+ | ブランチ | changeset消費 | バージョンバンプ | タグ形式 |
746
+ |---------|-------------|----------------|---------|
747
+ | staging | **消費しない** | なし(package.json据え置き) | `v{current}-rc.{run_number}` |
748
+ | main | `changeset version` で消費 | package.json更新 | `v{new_version}` |
749
+
750
+ ### 無限ループ防止(多重防御)
751
+
752
+ 1. `GITHUB_TOKEN` で作成されたpushイベントはデフォルトでワークフローを再トリガーしない
753
+ 2. コミットメッセージ `chore: release v` でのフィルタリング
754
+ 3. バージョンバンプコミットは `github-actions[bot]` 名義
755
+
756
+ ---
757
+
758
+ ## 10. 承認フロー
759
+
760
+ ### GitHub Environments
761
+
762
+ | Environment | Required Reviewers | Wait Timer | Deployment Branches |
763
+ |------------|-------------------|------------|-------------------|
764
+ | `staging` | なし | なし | `staging`のみ |
765
+ | `production` | 1名 | なし | `main`のみ |
766
+
767
+ ### 承認フロー詳細
768
+
769
+ ```mermaid
770
+ sequenceDiagram
771
+ participant Dev as 開発者
772
+ participant GH as GitHub Actions
773
+ participant Rev as Reviewer
774
+ participant Prod as Production
775
+
776
+ Dev->>GH: main push
777
+ GH->>GH: CI checks
778
+ GH->>Rev: ⚠️ 承認リクエスト
779
+ Note over Rev: GitHub UIで承認
780
+ Rev->>GH: ✅ 承認
781
+ GH->>Prod: Migrate + Deploy
782
+ GH->>GH: Release作成
783
+ ```
784
+
785
+ production環境へのデプロイは `migrate-production` ジョブで承認ゲートを設定。承認後にマイグレーションとデプロイが実行される。
786
+
787
+ ---
788
+
683
789
  ## 関連ドキュメント
684
790
 
685
791
  - [環境変数設計方針](./environment-variables.md)
@@ -688,11 +794,6 @@ sequenceDiagram
688
794
  - [Vercel CLI/APIリファレンス](../../instructions/vercel-cli-reference.md)
689
795
  <!-- @einja:managed:end -->
690
796
 
691
- ---
692
-
693
- <!-- @einja:seed:start id="deployment-project" -->
694
- ## プロジェクト固有の設定
695
-
696
- <!-- このセクションはプロジェクト固有の内容を追記する場所です -->
697
- <!-- einja syncで上書きされません -->
698
- <!-- @einja:seed:end -->
797
+ <!-- @einja:project-private:start id="deployment-project" -->
798
+ <!-- プロジェクト固有の情報を記入 -->
799
+ <!-- @einja:project-private:end -->
@@ -279,6 +279,7 @@ dotenvx採用により、GitHub Secretsは**環境ごとに1つの秘密鍵の
279
279
 
280
280
  | Secret名 | 用途 |
281
281
  |---------|------|
282
+ | `DOTENV_PRIVATE_KEY_DEVELOP` | dev検証環境の復号 |
282
283
  | `DOTENV_PRIVATE_KEY_STAGING` | ステージング環境の復号 |
283
284
  | `DOTENV_PRIVATE_KEY_PREVIEW` | Preview環境の復号(Neon環境変数含む) |
284
285
  | `DOTENV_PRIVATE_KEY_PRODUCTION` | 本番デプロイ時の復号 |
@@ -302,11 +303,6 @@ dotenvx採用により、GitHub Secretsは**環境ごとに1つの秘密鍵の
302
303
  - [デプロイセットアップ手順](../../instructions/deployment-setup.md)
303
304
  <!-- @einja:managed:end -->
304
305
 
305
- ---
306
-
307
- <!-- @einja:seed:start id="environment-variables-project" -->
308
- ## プロジェクト固有の設定
309
-
310
- <!-- このセクションはプロジェクト固有の内容を追記する場所です -->
311
- <!-- einja syncで上書きされません -->
312
- <!-- @einja:seed:end -->
306
+ <!-- @einja:project-private:start id="environment-variables-project" -->
307
+ <!-- プロジェクト固有の情報を記入 -->
308
+ <!-- @einja:project-private:end -->
@@ -541,11 +541,6 @@ describe('UserRepository', () => {
541
541
  すべての開発活動は、このビジョンと原則に従って実施してください。
542
542
  <!-- @einja:managed:end -->
543
543
 
544
- ---
545
-
546
- <!-- @einja:seed:start id="product-project" -->
547
- ## プロジェクト固有の設定
548
-
549
- <!-- このセクションはプロジェクト固有の内容を追記する場所です -->
550
- <!-- einja syncで上書きされません -->
551
- <!-- @einja:seed:end -->
544
+ <!-- @einja:project-private:start id="product-project" -->
545
+ <!-- プロジェクト固有の情報を記入 -->
546
+ <!-- @einja:project-private:end -->
@@ -87,12 +87,12 @@ GitHub Issueのチェックボックスでタスクグループのステータ
87
87
  - [x] 1.1 タスクグループ名
88
88
  ```
89
89
 
90
- **注意**: タスクグループの完了時、GitHub Issueのチェックボックス更新はユーザーが明示的に指示した場合のみ行います。`/einja:task-exec`コマンドは自動でIssueを更新しません。
90
+ **注意**: タスクグループの完了時、GitHub Issueのチェックボックス更新はユーザーが明示的に指示した場合のみ行います。`einja-task-exec` Skillは自動でIssueを更新しません。
91
91
 
92
92
  ### Issueのライフサイクル
93
93
 
94
- 1. **Issue作成**: `/einja:spec-create`コマンドで仕様書作成時に自動生成
95
- 2. **タスクグループ実行**: `/einja:task-exec #{issue_number} {タスクグループ番号}`でタスクグループを実行
94
+ 1. **Issue作成**: `einja-issue-spec-create` Skillで仕様書作成時に自動生成
95
+ 2. **タスクグループ実行**: `einja-task-exec` Skillで `#{issue_number} {タスクグループ番号}` を指定してタスクグループを実行
96
96
  3. **タスクグループ完了**: 実装・テスト・レビュー完了後、チェックボックスをON(手動更新)
97
97
  4. **Issue完了**: すべてのタスクグループが完了したらIssueをClose
98
98
 
@@ -356,7 +356,7 @@ TDDは**3タスク分割(X.Y.1 テスト / X.Y.2 実装 / X.Y.3 リファク
356
356
 
357
357
  ### 依存関係の記述形式(重要)
358
358
 
359
- **🔴 `pnpm task:loop`スクリプトが認識できる形式のみ使用すること**
359
+ **🔴 `/einja:issue-exec` が認識できる形式のみ使用すること**
360
360
 
361
361
  | 記述形式 | 意味 | 例 |
362
362
  |---------|------|-----|
@@ -375,9 +375,9 @@ TDDは**3タスク分割(X.Y.1 テスト / X.Y.2 実装 / X.Y.3 リファク
375
375
  > **詳細なフロー(仕様書作成からレビュー・マージまで)は[開発ワークフロー](development-workflow.md)を参照してください。**
376
376
 
377
377
  ### 1. タスクグループを選定・実行
378
- - `/einja:task-exec #{issue_number} {タスクグループ番号}`コマンドを実行
378
+ - `einja-task-exec` Skillで `#{issue_number} {タスクグループ番号}` を指定して実行
379
379
  - タスクグループ番号は必須引数(例: `1.1`, `2.3`)
380
- - **注意**: `pnpm task:loop <issue番号>`が何らかの理由で使えない場合のオプションの単発実行として`/einja:task-exec`を使用
380
+ - **注意**: 単一タスクグループを品質重視で確実に完了させたい場合に使用。`/einja:issue-exec` の Worker 内部でも呼ばれる
381
381
  - executer → reviewer → qa の3段階で実行
382
382
 
383
383
  ### 2. タスクを順次実装し、コミット
@@ -396,128 +396,40 @@ TDDは**3タスク分割(X.Y.1 テスト / X.Y.2 実装 / X.Y.3 リファク
396
396
  - または、ユーザーが明示的に指示した場合のみ自動更新
397
397
  - すべてのタスクグループが完了したら、IssueをClose
398
398
 
399
- ## Vibe-Kanbanタスク作成時の必須情報
400
-
401
- ### タスクタイトル形式
402
- ```
403
- [タスクグループ番号] タスクグループ名
404
- ```
405
-
406
- **例**: `[1.1] Server Core構築とDB設定`
407
-
408
- ### タスク説明形式
409
-
410
- ```markdown
411
- ## GitHub Issue
412
- #{issue_number}
413
-
414
- ## タスクグループ番号
415
- <タスクグループ番号>
416
-
417
- ## 概要
418
- <タスクグループの概要>
419
-
420
- ## タスク
421
- <GitHub Issueから抽出したタスク一覧>
422
-
423
- ## 依存関係
424
- <依存するタスクグループ番号>
425
-
426
- ## 完了条件
427
- <受け入れ基準を含む完了条件>
428
-
429
- ## 対応設計
430
- <design.mdの参照箇所>
431
- ```
432
-
433
- **例**:
434
- ```markdown
435
- ## GitHub Issue
436
- #17
437
-
438
- ## タスクグループ番号
439
- 1.1
440
-
441
- ## 概要
442
- packages/server-coreの初期化からDB接続設定まで、Server Coreの基盤構築を完了
443
-
444
- ## タスク
445
- - 1.1.1 packages/server-core初期化とtsconfig設定
446
- - 1.1.2 DB接続設定とマイグレーション
447
-
448
- ## 依存関係
449
- なし
450
-
451
- ## 完了条件
452
- server-coreパッケージが動作し、DBに接続できること(AC1.1を満たす)
453
-
454
- ## 対応設計
455
- design.md「Server Core構築」セクション
456
- ```
457
-
458
- ### 親Issue/サブIssue階層(task:loop使用時)
459
-
460
- `pnpm task:loop` 使用時は、Vibe-Kanban上でPhase→親Issue、タスクグループ→サブIssueの階層構造で管理されます。
461
-
462
- **親Issueタイトル形式**:
463
- ```
464
- [Issue{N} Phase{M}] {Phase名}
465
- ```
466
- 例: `[Issue17 Phase1] 基盤構築`
467
-
468
- **サブIssueタイトル形式**:
469
- ```
470
- [Issue{N} {X.Y}] {タスクグループ名}
471
- ```
472
- 例: `[Issue17 1.1] Server Core構築とDB設定`
473
-
474
- **親子関係の設定**: サブIssue作成後、REST API(PATCH `/api/remote/issues/{id}`)で `parent_issue_id` を設定します。
475
-
476
- **注意**: `/einja:task-exec` による単発実行時はこの階層構造は使用されません。`pnpm task:loop` 使用時のみ適用されます。
477
-
478
399
  ## コマンドリファレンス
479
400
 
480
401
  ### タスク管理関連コマンド
481
402
 
482
403
  **仕様書作成とIssue生成**:
483
- ```bash
484
- /einja:spec-create [タスク内容の説明]
485
- ```
404
+ `einja-issue-spec-create` Skillを使用し、タスク内容の説明を引数に指定します。
486
405
  - requirements.md、design.mdを作成し、GitHub Issueを自動生成
487
406
 
488
407
  **タスクグループ実行**:
489
- ```bash
490
- /einja:task-exec #{issue_number} {タスクグループ番号}
491
- ```
408
+ `einja-task-exec` Skillを使用し、`#{issue_number} {タスクグループ番号}` を引数に指定します。
492
409
  - Issue番号とタスクグループ番号は両方必須
493
410
  - executer → reviewer → qa の3段階で実行
494
411
  - QA合格後は追加指示待ち状態に入る
495
412
  - GitHub Issue更新はユーザーの明示的指示時のみ
496
- - **位置づけ**: `pnpm task:loop <issue番号>`が使えない場合の代替となる単発実行コマンド
413
+ - **位置づけ**: 単一タスクグループを品質重視で実行するSkill。`/einja:issue-exec` Worker 内部でも使用される
497
414
 
498
- **自動ループ実行**:
415
+ **Issue全体の並列実行**:
499
416
  ```bash
500
- pnpm task:loop <issue番号>
501
- pnpm task:loop <issue番号> --max-group <番号> # 指定番号まで実行
502
- pnpm task:loop <issue番号> --branch <ブランチ> # ベースブランチ指定
417
+ /einja:issue-exec #<issue番号>
418
+ /einja:issue-exec #<issue番号> --merge-mode auto # 全自動モード
419
+ /einja:issue-exec #<issue番号> --max-phase <番号> # 指定Phaseまで実行
420
+ /einja:issue-exec #<issue番号> --base <ブランチ> # ベースブランチ指定
503
421
  ```
504
- - 着手可能なタスクグループを並列でVibe-Kanbanに登録
505
- - Done状態を監視して次のタスクを自動開始
506
- - Phase毎に親Issueを作成し、タスクグループをサブIssueとして管理(詳細は「親Issue/サブIssue階層」を参照)
507
- - **前提**: `npx @einja/cli init` 実行済み、Claude Code インストール済み
422
+ - Manager → Director → Worker の3階層で並列実行
423
+ - tmux セッションで全プロセスを監視可能
424
+ - マージモードで自動化レベルを制御
508
425
 
509
426
  **仕様書からドキュメント更新**:
510
427
  ```bash
511
- /einja:update-docs-by-task-specs [タスク仕様書ディレクトリパス]
428
+ /einja:update-docs-by-issue-specs [Issue仕様書ディレクトリパス]
512
429
  ```
513
- - タスク仕様書の内容をfeature仕様書とsteering仕様書に反映
430
+ - Issue仕様書の内容をfeature仕様書とsteering仕様書に反映
514
431
  <!-- @einja:managed:end -->
515
432
 
516
- ---
517
-
518
- <!-- @einja:seed:start id="task-management-project" -->
519
- ## プロジェクト固有の設定
520
-
521
- <!-- このセクションはプロジェクト固有の内容を追記する場所です -->
522
- <!-- einja syncで上書きされません -->
523
- <!-- @einja:seed:end -->
433
+ <!-- @einja:project-private:start id="task-management-project" -->
434
+ <!-- プロジェクト固有の情報を記入 -->
435
+ <!-- @einja:project-private:end -->
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+ # Serena MCP サーバーの冪等起動
3
+ # .envrc から source して使用
4
+
5
+ # メインワークツリーをベースにする(worktree 間で共有)
6
+ _SERENA_BASE="${1:-$(pwd)}"
7
+ _SERENA_PORT_FILE="$_SERENA_BASE/.serena-port"
8
+ _SERENA_DEFAULT_PORT="${SERENA_PORT:-9850}"
9
+
10
+ # --- 既存インスタンスチェック(PIDベース) ---
11
+ if [ -f "$_SERENA_PORT_FILE" ]; then
12
+ read -r _saved_port _saved_pid < "$_SERENA_PORT_FILE"
13
+ if [ -n "$_saved_pid" ] && kill -0 "$_saved_pid" 2>/dev/null; then
14
+ # PIDが生存 → 自プロジェクトのSerena
15
+ export SERENA_PORT="$_saved_port"
16
+ return 0 2>/dev/null || true
17
+ fi
18
+ # PID死亡 → クリーンアップ
19
+ rm -f "$_SERENA_PORT_FILE"
20
+ fi
21
+
22
+ # --- uvx 確認 ---
23
+ if ! command -v uvx &> /dev/null; then
24
+ echo "[ensure-serena] Warning: uvx not found. Serena will not auto-start." >&2
25
+ echo "[ensure-serena] Install uv first: curl -LsSf https://astral.sh/uv/install.sh | sh" >&2
26
+ return 0 2>/dev/null || true
27
+ fi
28
+
29
+ # --- 空きポート検出 ---
30
+ _port="$_SERENA_DEFAULT_PORT"
31
+ _port_found=false
32
+ for _i in $(seq 1 10); do
33
+ if ! nc -z 127.0.0.1 "$_port" > /dev/null 2>&1; then
34
+ _port_found=true
35
+ break
36
+ fi
37
+ _port=$((_port + 1))
38
+ done
39
+
40
+ if [ "$_port_found" = false ]; then
41
+ echo "[ensure-serena] Error: No available port found (tried $_SERENA_DEFAULT_PORT-$_port)" >&2
42
+ return 0 2>/dev/null || true
43
+ fi
44
+
45
+ # --- バックグラウンド起動 ---
46
+ echo "[ensure-serena] Starting Serena on port $_port..."
47
+ uvx --from git+https://github.com/oraios/serena \
48
+ serena start-mcp-server \
49
+ --transport streamable-http \
50
+ --host 127.0.0.1 \
51
+ --port "$_port" \
52
+ --context claude-code \
53
+ --project "$_SERENA_BASE" \
54
+ > /dev/null 2>&1 &
55
+ _serena_pid=$!
56
+ disown
57
+
58
+ # --- 起動待機(PID生存 + ポートLISTEN、最大30秒) ---
59
+ for _i in $(seq 1 60); do
60
+ if ! kill -0 "$_serena_pid" 2>/dev/null; then
61
+ echo "[ensure-serena] Warning: Serena process exited unexpectedly" >&2
62
+ return 0 2>/dev/null || true
63
+ fi
64
+ if nc -z 127.0.0.1 "$_port" > /dev/null 2>&1; then
65
+ echo "$_port $_serena_pid" > "$_SERENA_PORT_FILE"
66
+ export SERENA_PORT="$_port"
67
+ echo "[ensure-serena] Serena ready on port $_port (PID: $_serena_pid)"
68
+ return 0 2>/dev/null || true
69
+ fi
70
+ sleep 0.5
71
+ done
72
+
73
+ # タイムアウト(起動失敗してもdirenvはブロックしない)
74
+ echo "[ensure-serena] Warning: Serena failed to start within 30s" >&2
75
+ return 0 2>/dev/null || true