@ronkovic/aad 0.3.0

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +312 -0
  3. package/bin/aad.js +2 -0
  4. package/package.json +78 -0
  5. package/src/__tests__/e2e/pipeline-e2e.test.ts +279 -0
  6. package/src/__tests__/e2e/resume-e2e.test.ts +200 -0
  7. package/src/__tests__/integration/cli-smoke.test.ts +175 -0
  8. package/src/__tests__/integration/pipeline.test.ts +346 -0
  9. package/src/bun-imports.d.ts +14 -0
  10. package/src/main.ts +52 -0
  11. package/src/modules/claude-provider/__tests__/claude-cli.adapter.test.ts +277 -0
  12. package/src/modules/claude-provider/__tests__/claude-sdk-real-env.test.ts +127 -0
  13. package/src/modules/claude-provider/__tests__/claude-sdk.adapter.test.ts +347 -0
  14. package/src/modules/claude-provider/__tests__/effort-strategy.test.ts +212 -0
  15. package/src/modules/claude-provider/__tests__/provider-registry.test.ts +251 -0
  16. package/src/modules/claude-provider/__tests__/retry.test.ts +201 -0
  17. package/src/modules/claude-provider/claude-cli.adapter.ts +156 -0
  18. package/src/modules/claude-provider/claude-provider.port.ts +35 -0
  19. package/src/modules/claude-provider/claude-sdk.adapter.ts +217 -0
  20. package/src/modules/claude-provider/effort-strategy.ts +94 -0
  21. package/src/modules/claude-provider/index.ts +32 -0
  22. package/src/modules/claude-provider/provider-registry.ts +92 -0
  23. package/src/modules/claude-provider/retry.ts +81 -0
  24. package/src/modules/cli/__tests__/app.test.ts +160 -0
  25. package/src/modules/cli/__tests__/cleanup.test.ts +111 -0
  26. package/src/modules/cli/__tests__/commands.test.ts +186 -0
  27. package/src/modules/cli/__tests__/output.test.ts +329 -0
  28. package/src/modules/cli/__tests__/resume.test.ts +324 -0
  29. package/src/modules/cli/__tests__/run.test.ts +168 -0
  30. package/src/modules/cli/__tests__/shutdown.test.ts +168 -0
  31. package/src/modules/cli/__tests__/status.test.ts +144 -0
  32. package/src/modules/cli/app.ts +241 -0
  33. package/src/modules/cli/commands/cleanup.ts +120 -0
  34. package/src/modules/cli/commands/resume.ts +156 -0
  35. package/src/modules/cli/commands/run.ts +322 -0
  36. package/src/modules/cli/commands/status.ts +101 -0
  37. package/src/modules/cli/index.ts +29 -0
  38. package/src/modules/cli/output.ts +256 -0
  39. package/src/modules/cli/shutdown.ts +122 -0
  40. package/src/modules/dashboard/__tests__/api-routes.test.ts +204 -0
  41. package/src/modules/dashboard/__tests__/file-watcher.test.ts +34 -0
  42. package/src/modules/dashboard/__tests__/server.test.ts +120 -0
  43. package/src/modules/dashboard/__tests__/sse-broadcaster.test.ts +163 -0
  44. package/src/modules/dashboard/__tests__/sse-routes.test.ts +58 -0
  45. package/src/modules/dashboard/__tests__/state-aggregator.test.ts +330 -0
  46. package/src/modules/dashboard/index.ts +8 -0
  47. package/src/modules/dashboard/routes/api.ts +84 -0
  48. package/src/modules/dashboard/routes/sse.ts +37 -0
  49. package/src/modules/dashboard/server.ts +111 -0
  50. package/src/modules/dashboard/services/file-watcher.ts +36 -0
  51. package/src/modules/dashboard/services/sse-broadcaster.ts +81 -0
  52. package/src/modules/dashboard/services/state-aggregator.ts +132 -0
  53. package/src/modules/dashboard/ui/dashboard.html +405 -0
  54. package/src/modules/git-workspace/__tests__/branch-manager.test.ts +335 -0
  55. package/src/modules/git-workspace/__tests__/git-exec.test.ts +91 -0
  56. package/src/modules/git-workspace/__tests__/memory-sync.test.ts +273 -0
  57. package/src/modules/git-workspace/__tests__/merge-service.test.ts +286 -0
  58. package/src/modules/git-workspace/__tests__/settings-merge.test.ts +163 -0
  59. package/src/modules/git-workspace/__tests__/worktree-manager.test.ts +247 -0
  60. package/src/modules/git-workspace/branch-manager.ts +191 -0
  61. package/src/modules/git-workspace/git-exec.ts +124 -0
  62. package/src/modules/git-workspace/index.ts +17 -0
  63. package/src/modules/git-workspace/memory-sync.ts +89 -0
  64. package/src/modules/git-workspace/merge-service.ts +156 -0
  65. package/src/modules/git-workspace/settings-merge.ts +95 -0
  66. package/src/modules/git-workspace/worktree-manager.ts +199 -0
  67. package/src/modules/logging/__tests__/log-store.test.ts +242 -0
  68. package/src/modules/logging/__tests__/logger.test.ts +81 -0
  69. package/src/modules/logging/__tests__/sse-transport.test.ts +93 -0
  70. package/src/modules/logging/index.ts +7 -0
  71. package/src/modules/logging/log-store.ts +80 -0
  72. package/src/modules/logging/logger.ts +55 -0
  73. package/src/modules/logging/transports/sse-transport.ts +28 -0
  74. package/src/modules/multi-repo/__tests__/multi-repo-planner.test.ts +93 -0
  75. package/src/modules/multi-repo/__tests__/repo-context.test.ts +79 -0
  76. package/src/modules/multi-repo/index.ts +12 -0
  77. package/src/modules/multi-repo/multi-repo-planner.ts +112 -0
  78. package/src/modules/multi-repo/repo-context.ts +71 -0
  79. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/progress.json +10 -0
  80. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/queue/completed/task-getall-2.json +10 -0
  81. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/queue/pending/task-1.json +13 -0
  82. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/queue/pending/task-getall-1.json +10 -0
  83. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/queue/pending/task-status-change.json +10 -0
  84. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/workers/worker-1.json +5 -0
  85. package/src/modules/persistence/__tests__/.tmp-stores-test-81991/workers/worker-2.json +5 -0
  86. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/progress.json +10 -0
  87. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/queue/completed/task-getall-2.json +10 -0
  88. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/queue/pending/task-1.json +13 -0
  89. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/queue/pending/task-getall-1.json +10 -0
  90. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/queue/pending/task-status-change.json +10 -0
  91. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/workers/worker-1.json +5 -0
  92. package/src/modules/persistence/__tests__/.tmp-stores-test-82469/workers/worker-2.json +5 -0
  93. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/progress.json +10 -0
  94. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/queue/completed/task-getall-2.json +10 -0
  95. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/queue/pending/task-1.json +13 -0
  96. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/queue/pending/task-getall-1.json +10 -0
  97. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/queue/pending/task-status-change.json +10 -0
  98. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/workers/worker-1.json +5 -0
  99. package/src/modules/persistence/__tests__/.tmp-stores-test-85301/workers/worker-2.json +5 -0
  100. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/progress.json +10 -0
  101. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/queue/completed/task-getall-2.json +10 -0
  102. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/queue/pending/task-1.json +13 -0
  103. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/queue/pending/task-getall-1.json +10 -0
  104. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/queue/pending/task-status-change.json +10 -0
  105. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/workers/worker-1.json +5 -0
  106. package/src/modules/persistence/__tests__/.tmp-stores-test-85759/workers/worker-2.json +5 -0
  107. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/progress.json +10 -0
  108. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/queue/completed/task-getall-2.json +10 -0
  109. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/queue/pending/task-1.json +13 -0
  110. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/queue/pending/task-getall-1.json +10 -0
  111. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/queue/pending/task-status-change.json +10 -0
  112. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/workers/worker-1.json +5 -0
  113. package/src/modules/persistence/__tests__/.tmp-stores-test-86184/workers/worker-2.json +5 -0
  114. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/progress.json +10 -0
  115. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/queue/completed/task-getall-2.json +10 -0
  116. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/queue/pending/task-1.json +13 -0
  117. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/queue/pending/task-getall-1.json +10 -0
  118. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/queue/pending/task-status-change.json +10 -0
  119. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/workers/worker-1.json +5 -0
  120. package/src/modules/persistence/__tests__/.tmp-stores-test-88026/workers/worker-2.json +5 -0
  121. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/progress.json +10 -0
  122. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/queue/completed/task-getall-2.json +10 -0
  123. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/queue/pending/task-1.json +13 -0
  124. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/queue/pending/task-getall-1.json +10 -0
  125. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/queue/pending/task-status-change.json +10 -0
  126. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/workers/worker-1.json +5 -0
  127. package/src/modules/persistence/__tests__/.tmp-stores-test-89475/workers/worker-2.json +5 -0
  128. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/progress.json +10 -0
  129. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/queue/completed/task-getall-2.json +10 -0
  130. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/queue/pending/task-1.json +13 -0
  131. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/queue/pending/task-getall-1.json +10 -0
  132. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/queue/pending/task-status-change.json +10 -0
  133. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/workers/worker-1.json +5 -0
  134. package/src/modules/persistence/__tests__/.tmp-stores-test-89924/workers/worker-2.json +5 -0
  135. package/src/modules/persistence/__tests__/file-lock.test.ts +141 -0
  136. package/src/modules/persistence/__tests__/index.test.ts +38 -0
  137. package/src/modules/persistence/__tests__/stores.test.ts +594 -0
  138. package/src/modules/persistence/file-lock.ts +158 -0
  139. package/src/modules/persistence/fs-run-store.ts +73 -0
  140. package/src/modules/persistence/fs-task-store.ts +152 -0
  141. package/src/modules/persistence/fs-worker-store.ts +116 -0
  142. package/src/modules/persistence/in-memory-stores.ts +98 -0
  143. package/src/modules/persistence/index.ts +60 -0
  144. package/src/modules/persistence/stores.port.ts +60 -0
  145. package/src/modules/planning/__tests__/file-conflict-validator.test.ts +256 -0
  146. package/src/modules/planning/__tests__/planning-service.test.ts +366 -0
  147. package/src/modules/planning/__tests__/project-detection.test.ts +707 -0
  148. package/src/modules/planning/file-conflict-validator.ts +135 -0
  149. package/src/modules/planning/index.ts +40 -0
  150. package/src/modules/planning/planning.service.ts +262 -0
  151. package/src/modules/planning/project-detection.ts +525 -0
  152. package/src/modules/plugin/__tests__/plugin-loader.test.ts +83 -0
  153. package/src/modules/plugin/__tests__/plugin-manager.test.ts +187 -0
  154. package/src/modules/plugin/index.ts +3 -0
  155. package/src/modules/plugin/plugin-loader.ts +46 -0
  156. package/src/modules/plugin/plugin-manager.ts +90 -0
  157. package/src/modules/plugin/plugin.types.ts +37 -0
  158. package/src/modules/process-manager/__tests__/process-manager.test.ts +210 -0
  159. package/src/modules/process-manager/__tests__/worker.test.ts +89 -0
  160. package/src/modules/process-manager/index.ts +5 -0
  161. package/src/modules/process-manager/process-manager.ts +193 -0
  162. package/src/modules/process-manager/worker.ts +106 -0
  163. package/src/modules/task-execution/__tests__/default-spawner.test.ts +154 -0
  164. package/src/modules/task-execution/__tests__/executor.test.ts +760 -0
  165. package/src/modules/task-execution/__tests__/implementer-green.test.ts +286 -0
  166. package/src/modules/task-execution/__tests__/merge-phase.test.ts +368 -0
  167. package/src/modules/task-execution/__tests__/reviewer.test.ts +302 -0
  168. package/src/modules/task-execution/__tests__/tester-red.test.ts +281 -0
  169. package/src/modules/task-execution/__tests__/tester-verify.test.ts +313 -0
  170. package/src/modules/task-execution/executor.ts +303 -0
  171. package/src/modules/task-execution/index.ts +45 -0
  172. package/src/modules/task-execution/phases/default-spawner.ts +49 -0
  173. package/src/modules/task-execution/phases/implementer-green.ts +100 -0
  174. package/src/modules/task-execution/phases/merge.ts +122 -0
  175. package/src/modules/task-execution/phases/reviewer.ts +160 -0
  176. package/src/modules/task-execution/phases/tester-red.ts +100 -0
  177. package/src/modules/task-execution/phases/tester-verify.ts +120 -0
  178. package/src/modules/task-queue/__tests__/dependency-resolver.test.ts +456 -0
  179. package/src/modules/task-queue/__tests__/dispatcher.test.ts +824 -0
  180. package/src/modules/task-queue/__tests__/task-plan.test.ts +122 -0
  181. package/src/modules/task-queue/__tests__/task.test.ts +130 -0
  182. package/src/modules/task-queue/dependency-resolver.ts +171 -0
  183. package/src/modules/task-queue/dispatcher.ts +372 -0
  184. package/src/modules/task-queue/index.ts +16 -0
  185. package/src/modules/task-queue/task-plan.ts +40 -0
  186. package/src/modules/task-queue/task.ts +67 -0
  187. package/src/shared/__tests__/config.test.ts +204 -0
  188. package/src/shared/__tests__/errors.test.ts +285 -0
  189. package/src/shared/__tests__/events.test.ts +496 -0
  190. package/src/shared/__tests__/types.test.ts +360 -0
  191. package/src/shared/config.ts +133 -0
  192. package/src/shared/errors.ts +128 -0
  193. package/src/shared/events.ts +171 -0
  194. package/src/shared/types.ts +143 -0
  195. package/tsconfig.json +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AAD Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,312 @@
1
+ # AAD - Autonomous Agent Development Orchestrator
2
+
3
+ TypeScript/Bun製マルチエージェント開発オーケストレーター。Claude CLIを活用し、TDDパイプラインによる並列タスク実行を自動化します。
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue)](https://www.typescriptlang.org/)
7
+ [![Bun](https://img.shields.io/badge/Bun-1.2+-black)](https://bun.sh/)
8
+ [![Tests](https://img.shields.io/badge/tests-738%2B%20passing-brightgreen)]()
9
+ [![Version](https://img.shields.io/badge/version-0.3.0-orange)]()
10
+
11
+ ## 主要機能
12
+
13
+ - **マルチエージェント並列実行**: 複数のClaudeエージェントが独立したタスクを並列処理
14
+ - **TDDパイプライン**: Red → Green → Verify → Review → Merge の自動化されたテスト駆動開発
15
+ - **マルチリポジトリ対応**: 複数リポジトリにまたがるタスクの統合管理 *(v0.3.0)*
16
+ - **プラグインシステム**: カスタムアダプター・パイプラインステップの拡張 *(v0.3.0)*
17
+ - **Git Workspace管理**: タスクごとに独立したworktreeを自動作成・管理
18
+ - **依存関係解決**: タスク間の依存関係を自動検出し、適切な順序で実行
19
+ - **リアルタイム監視**: Webダッシュボードで進捗・ログをリアルタイム表示
20
+ - **構造化ログ**: pinoによる構造化ログで詳細なトレーシングが可能
21
+
22
+ ## アーキテクチャ
23
+
24
+ AADは12個のモジュールで構成された**Hexagonal-flavored Modular Monolith**です:
25
+
26
+ ```
27
+ cli (エントリポイント)
28
+ ├── planning (要件→タスク分解) ★
29
+ ├── task-queue (タスクライフサイクル管理)
30
+ ├── task-execution (TDDパイプライン実行) ★
31
+ ├── process-manager (ワーカープロセス管理)
32
+ ├── git-workspace (worktree/branch管理)
33
+ ├── claude-provider (SDK/CLI抽象化) ★
34
+ ├── persistence (状態永続化) ★
35
+ ├── logging (構造化ログ)
36
+ ├── dashboard (Web UI)
37
+ ├── multi-repo (マルチリポジトリ統合) ★
38
+ └── plugin (プラグインシステム) ★
39
+
40
+ ★ = Ports & Adapters パターン適用
41
+ ```
42
+
43
+ ### 技術スタック
44
+
45
+ - **言語**: TypeScript (strict mode)
46
+ - **ランタイム**: Bun v1.2+
47
+ - **テストフレームワーク**: bun:test (Jest互換API)
48
+ - **Web Framework**: Hono
49
+ - **ロガー**: pino v9
50
+ - **バリデーション**: Zod
51
+ - **CLI**: Commander.js
52
+
53
+ ## インストール
54
+
55
+ > ⚠️ **Bun専用** — AADはBunランタイムが必要です。Node.jsでは動作しません。
56
+
57
+ ### 前提条件
58
+
59
+ - [Bun](https://bun.sh/) v1.2 以上
60
+ - Git
61
+ - Claude CLI (オプション: CLI adapter使用時)
62
+
63
+ ### インストール不要で実行 (推奨)
64
+
65
+ ```bash
66
+ bunx aad run requirements.md
67
+ ```
68
+
69
+ ### グローバルインストール
70
+
71
+ ```bash
72
+ bun install -g aad
73
+ aad run requirements.md
74
+ ```
75
+
76
+ ### スタンドアロンバイナリ
77
+
78
+ ```bash
79
+ git clone https://github.com/ronkovic/aad.git
80
+ cd aad && bun install
81
+ bun run build # → ./aad バイナリを生成
82
+ ./aad --version
83
+ ```
84
+
85
+ ### ローカル開発
86
+
87
+ ```bash
88
+ git clone https://github.com/ronkovic/aad.git
89
+ cd aad
90
+ bun install
91
+ bun run dev
92
+ ```
93
+
94
+ ## クイックスタート
95
+
96
+ ### 1. 要件ファイルの作成
97
+
98
+ `requirements.md` を作成してタスクを記述:
99
+
100
+ ```markdown
101
+ # タスク一覧
102
+
103
+ ## Task 1: ユーザー認証機能の実装
104
+ - ファイル: src/auth/login.ts
105
+ - テスト: src/auth/__tests__/login.test.ts
106
+ - 依存: なし
107
+
108
+ ## Task 2: ダッシュボードUI作成
109
+ - ファイル: src/ui/dashboard.tsx
110
+ - テスト: src/ui/__tests__/dashboard.test.tsx
111
+ - 依存: Task 1
112
+ ```
113
+
114
+ ### 2. タスク実行
115
+
116
+ ```bash
117
+ aad run requirements.md --workers 4
118
+ ```
119
+
120
+ AADが自動的に:
121
+ 1. タスクを分解・依存関係を解析
122
+ 2. 各タスク用のworktreeを作成
123
+ 3. 4つのワーカーで並列実行 (TDD: テスト作成 → 実装 → 検証 → レビュー)
124
+ 4. 親ブランチへのマージ
125
+
126
+ ### 3. 進捗確認
127
+
128
+ ```bash
129
+ # ステータス確認
130
+ aad status
131
+
132
+ # 実行の再開
133
+ aad resume <run_id>
134
+
135
+ # worktreeのクリーンアップ
136
+ aad cleanup
137
+ ```
138
+
139
+ ### 4. Webダッシュボード (オプション)
140
+
141
+ ```bash
142
+ aad run requirements.md --workers 4 --dashboard
143
+ ```
144
+
145
+ ブラウザで `http://localhost:7333` を開くと、リアルタイムで進捗・ログ・依存グラフを確認できます。
146
+
147
+ ## 開発ガイド
148
+
149
+ ### 環境セットアップ
150
+
151
+ ```bash
152
+ # 依存関係のインストール
153
+ bun install
154
+
155
+ # 型チェック
156
+ bun run typecheck
157
+
158
+ # テスト実行
159
+ bun test
160
+
161
+ # ウォッチモード
162
+ bun test --watch
163
+
164
+ # Lint
165
+ bun run lint
166
+ ```
167
+
168
+ ### ビルド & 配布
169
+
170
+ ```bash
171
+ # 単一バイナリのビルド (self-contained実行ファイル)
172
+ bun build --compile ./src/main.ts --outfile aad
173
+
174
+ # 実行
175
+ ./aad --version
176
+ ```
177
+
178
+ ### モジュール境界ルール
179
+
180
+ 各モジュールは `index.ts` でのみ公開APIをエクスポートします:
181
+
182
+ ```typescript
183
+ // ✅ Good
184
+ import { TaskQueue } from "@aad/task-queue";
185
+
186
+ // ❌ Bad: モジュール内部へのアクセス
187
+ import { Dispatcher } from "@aad/task-queue/dispatcher";
188
+ ```
189
+
190
+ ### テストの書き方
191
+
192
+ ```typescript
193
+ import { describe, test, expect } from "bun:test";
194
+
195
+ describe("MyModule", () => {
196
+ test("should do something", () => {
197
+ expect(true).toBe(true);
198
+ });
199
+ });
200
+ ```
201
+
202
+ ## 設定
203
+
204
+ `.aad/config.json` で動作をカスタマイズできます:
205
+
206
+ ```json
207
+ {
208
+ "workers": {
209
+ "num": 4,
210
+ "max": 8
211
+ },
212
+ "models": {
213
+ "default": "sonnet",
214
+ "splitter": "sonnet",
215
+ "tester": "sonnet",
216
+ "implementer": "sonnet",
217
+ "reviewer": "sonnet",
218
+ "mergeResolver": "haiku"
219
+ },
220
+ "timeouts": {
221
+ "claude": 1200,
222
+ "test": 600
223
+ },
224
+ "dashboard": {
225
+ "enabled": true,
226
+ "port": 7333
227
+ }
228
+ }
229
+ ```
230
+
231
+ ### 利用可能なモデル
232
+
233
+ `models`設定で指定できるモデル名:
234
+
235
+ | フルネーム | 短縮名 | 説明 |
236
+ |-----------|--------|------|
237
+ | claude-sonnet-4-5-20250929 | sonnet | Sonnet 4.5 - バランス型、推奨デフォルト |
238
+ | claude-opus-4-6 | opus | Opus 4.6 - 最高性能、高コスト |
239
+ | claude-haiku-4-5-20251001 | haiku | Haiku 4.5 - 高速・低コスト |
240
+
241
+ 設定では短縮名(`sonnet`、`opus`、`haiku`)またはフルネームが使用できます。
242
+
243
+ ## Claude Provider: SDK vs CLI
244
+
245
+ AADはClaudeとの通信に2つのadapterを提供:
246
+
247
+ - **SDK Adapter** (`claude-sdk.adapter.ts`): Agent SDK経由、構造化出力に最適
248
+ - **CLI Adapter** (`claude-cli.adapter.ts`): Claude CLI経由、重いファイル操作に最適
249
+
250
+ サービスごとに使い分け可能:
251
+
252
+ ```typescript
253
+ const providerConfig = {
254
+ default: 'cli',
255
+ overrides: {
256
+ splitter: 'sdk', // 構造化JSON出力
257
+ reviewer: 'sdk', // 構造化レビュー結果
258
+ }
259
+ };
260
+ ```
261
+
262
+ ## トラブルシューティング
263
+
264
+ ### ログの確認
265
+
266
+ ```bash
267
+ # 構造化ログの確認
268
+ cat .aad/docs/<run_id>/logs/structured.jsonl | bunx pino-pretty
269
+ ```
270
+
271
+ ### Worktreeが残っている
272
+
273
+ ```bash
274
+ aad cleanup --all
275
+ ```
276
+
277
+ ### タスクがスタックした
278
+
279
+ ```bash
280
+ # ステータス確認
281
+ aad status <run_id>
282
+
283
+ # 強制クリーンアップ
284
+ aad cleanup --run <run_id> --force
285
+ ```
286
+
287
+ ## ライセンス
288
+
289
+ [MIT License](LICENSE)
290
+
291
+ ## 貢献
292
+
293
+ コントリビューションを歓迎します! 詳細は [CONTRIBUTING.md](CONTRIBUTING.md) をご覧ください。
294
+
295
+ ### 開発の流れ
296
+
297
+ 1. このリポジトリをfork
298
+ 2. feature branchを作成 (`git checkout -b feature/amazing-feature`)
299
+ 3. 変更をcommit (`git commit -m 'feat: add amazing feature'`)
300
+ 4. branchをpush (`git push origin feature/amazing-feature`)
301
+ 5. Pull Requestを作成
302
+
303
+ ## リンク
304
+
305
+ - [Architecture Documentation](docs/architecture.md)
306
+ - [Rewrite Plan (Internal)](docs/rewrite-plan/README.md)
307
+ - [Project Guidelines](CLAUDE.md)
308
+ - [Issue Tracker](https://github.com/ronkovic/aad/issues)
309
+
310
+ ---
311
+
312
+ Built with ❤️ using [Bun](https://bun.sh/) and [Claude](https://www.anthropic.com/claude)
package/bin/aad.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import "../src/main.ts";
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@ronkovic/aad",
3
+ "version": "0.3.0",
4
+ "description": "Autonomous Agent Development Orchestrator - Multi-agent TDD pipeline powered by Claude",
5
+ "module": "src/main.ts",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "bin": {
9
+ "aad": "./bin/aad.js"
10
+ },
11
+ "files": [
12
+ "bin",
13
+ "src",
14
+ "README.md",
15
+ "LICENSE",
16
+ "tsconfig.json"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "bun": "./src/main.ts",
21
+ "import": "./src/main.ts",
22
+ "types": "./src/main.ts"
23
+ }
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "dev": "bun run src/main.ts",
30
+ "build": "bun build --compile ./src/main.ts --outfile aad",
31
+ "test": "bun test",
32
+ "test:watch": "bun test --watch",
33
+ "test:coverage": "bun test --coverage",
34
+ "test:coverage:report": "bun test --coverage --coverage-reporter=html",
35
+ "typecheck": "tsc --noEmit",
36
+ "lint": "eslint src/",
37
+ "prepublishOnly": "bun run typecheck && bun run lint && bun test"
38
+ },
39
+ "dependencies": {
40
+ "@anthropic-ai/claude-agent-sdk": "^0.2.34",
41
+ "hono": "^4.6",
42
+ "pino": "^9.6",
43
+ "pino-pretty": "^13.0",
44
+ "chokidar": "^4.0",
45
+ "commander": "^13.0",
46
+ "zod": "^3.24"
47
+ },
48
+ "devDependencies": {
49
+ "@types/bun": "latest",
50
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
51
+ "@typescript-eslint/parser": "^8.54.0",
52
+ "eslint": "^10.0.0",
53
+ "typescript": "^5.7"
54
+ },
55
+ "engines": {
56
+ "bun": ">=1.2.0"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/ronkovic/aad.git"
61
+ },
62
+ "homepage": "https://github.com/ronkovic/aad#readme",
63
+ "bugs": {
64
+ "url": "https://github.com/ronkovic/aad/issues"
65
+ },
66
+ "author": "ronkovic",
67
+ "keywords": [
68
+ "claude",
69
+ "agent",
70
+ "tdd",
71
+ "orchestrator",
72
+ "multi-agent",
73
+ "autonomous",
74
+ "development",
75
+ "bun"
76
+ ],
77
+ "license": "MIT"
78
+ }
@@ -0,0 +1,279 @@
1
+ /**
2
+ * E2E Pipeline Test — lightweight, mock-based
3
+ * Tests the full planning → dispatch → completion flow without real Claude API or git.
4
+ */
5
+ import { describe, test, expect, beforeEach } from "bun:test";
6
+ import { EventBus, type AADEvent } from "@aad/shared/events";
7
+ import { PlanningService } from "@aad/planning/planning.service";
8
+ import { Dispatcher } from "@aad/task-queue/dispatcher";
9
+ import { createStores } from "@aad/persistence/index";
10
+ import {
11
+ createRunId,
12
+ createTaskId,
13
+ createWorkerId,
14
+ type TaskId,
15
+ } from "@aad/shared/types";
16
+ import type { Config } from "@aad/shared/config";
17
+ import type {
18
+ ClaudeProvider,
19
+ ClaudeRequest,
20
+ ClaudeResponse,
21
+ } from "@aad/claude-provider/claude-provider.port";
22
+ import type { FileChecker } from "@aad/planning/project-detection";
23
+ import type pino from "pino";
24
+
25
+ // ── Helpers ──────────────────────────────────────────────
26
+
27
+ class MockClaudeProvider implements ClaudeProvider {
28
+ mockResponse: ClaudeResponse = {
29
+ result: "",
30
+ exitCode: 0,
31
+ model: "claude-sonnet-4-5",
32
+ effortLevel: "medium",
33
+ duration: 100,
34
+ };
35
+
36
+ async call(_req: ClaudeRequest): Promise<ClaudeResponse> {
37
+ return this.mockResponse;
38
+ }
39
+ }
40
+
41
+ function createMockLogger(): pino.Logger {
42
+ const noop = () => {};
43
+ return {
44
+ info: noop, warn: noop, error: noop, debug: noop, trace: noop, fatal: noop,
45
+ child: () => createMockLogger(),
46
+ } as unknown as pino.Logger;
47
+ }
48
+
49
+ function createMockConfig(): Config {
50
+ return {
51
+ workers: { num: 2, max: 4 },
52
+ models: {},
53
+ timeouts: { claude: 1200, test: 600, staleTask: 5400 },
54
+ retry: { maxRetries: 2 },
55
+ debug: false,
56
+ adaptiveEffort: false,
57
+ teams: { splitter: false, reviewer: false },
58
+ memorySync: false,
59
+ dashboard: { enabled: false, port: 7333, host: "localhost" },
60
+ };
61
+ }
62
+
63
+ const mockFileChecker: FileChecker = {
64
+ exists: async () => false,
65
+ readText: async () => "",
66
+ glob: async () => [],
67
+ };
68
+
69
+ /** Collect specific event types into an array */
70
+ function collectEvents(eventBus: EventBus, ...types: string[]) {
71
+ const collected: AADEvent[] = [];
72
+ for (const t of types) {
73
+ eventBus.on(t as AADEvent["type"], (e: AADEvent) => collected.push(e));
74
+ }
75
+ return collected;
76
+ }
77
+
78
+ /** Wait until predicate is true (polling) */
79
+ function waitFor(predicate: () => boolean, timeoutMs = 5000): Promise<void> {
80
+ return new Promise((resolve, reject) => {
81
+ const start = Date.now();
82
+ const check = () => {
83
+ if (predicate()) return resolve();
84
+ if (Date.now() - start > timeoutMs) return reject(new Error("waitFor timeout"));
85
+ setTimeout(check, 20);
86
+ };
87
+ check();
88
+ });
89
+ }
90
+
91
+ // ── Tests ────────────────────────────────────────────────
92
+
93
+ describe("E2E Pipeline", () => {
94
+ let eventBus: EventBus;
95
+ let mockProvider: MockClaudeProvider;
96
+ let logger: pino.Logger;
97
+
98
+ beforeEach(() => {
99
+ eventBus = new EventBus();
100
+ mockProvider = new MockClaudeProvider();
101
+ logger = createMockLogger();
102
+ });
103
+
104
+ test("basic pipeline: plan → dispatch → complete", async () => {
105
+ const config = createMockConfig();
106
+ const stores = createStores("memory");
107
+ const runId = createRunId("e2e-run-1");
108
+
109
+ // 1) Planning — mock Claude to return a 2-task plan
110
+ mockProvider.mockResponse = {
111
+ result: JSON.stringify({
112
+ run_id: "e2e-run-1",
113
+ parent_branch: "main",
114
+ tasks: [
115
+ { task_id: "task-1", title: "Task 1", description: "First", files_to_modify: ["a.ts"], depends_on: [], priority: 1 },
116
+ { task_id: "task-2", title: "Task 2", description: "Second", files_to_modify: ["b.ts"], depends_on: [], priority: 2 },
117
+ ],
118
+ }),
119
+ exitCode: 0,
120
+ model: "claude-sonnet-4-5",
121
+ effortLevel: "medium",
122
+ duration: 100,
123
+ };
124
+
125
+ const planningService = new PlanningService(mockProvider, eventBus, config, logger, { fileChecker: mockFileChecker });
126
+
127
+ const events = collectEvents(eventBus,
128
+ "planning:started", "planning:completed", "task:dispatched", "run:completed",
129
+ );
130
+
131
+ const taskPlan = await planningService.planTasks({
132
+ runId,
133
+ parentBranch: "main",
134
+ requirementsPath: "/fake/requirements.md",
135
+ targetDocsDir: "/fake/docs",
136
+ });
137
+
138
+ expect(taskPlan.tasks).toHaveLength(2);
139
+
140
+ // 2) Dispatch
141
+ // Register idle workers
142
+ const w1 = createWorkerId("worker-1");
143
+ const w2 = createWorkerId("worker-2");
144
+ await stores.workerStore.save({ workerId: w1, status: "idle", currentTask: null });
145
+ await stores.workerStore.save({ workerId: w2, status: "idle", currentTask: null });
146
+
147
+ const dispatcher = new Dispatcher({
148
+ taskStore: stores.taskStore,
149
+ workerStore: stores.workerStore,
150
+ runStore: stores.runStore,
151
+ eventBus,
152
+ config: { maxRetries: 2 },
153
+ logger,
154
+ });
155
+
156
+ await dispatcher.initialize(taskPlan);
157
+ dispatcher.start();
158
+
159
+ // Wait for tasks to be dispatched
160
+ await waitFor(() => events.some(e => e.type === "task:dispatched"), 3000);
161
+
162
+ // 3) Simulate task completion
163
+ eventBus.emit({ type: "task:completed", taskId: createTaskId("task-1"), result: { taskId: createTaskId("task-1"), status: "completed", duration: 50 } });
164
+ eventBus.emit({ type: "task:completed", taskId: createTaskId("task-2"), result: { taskId: createTaskId("task-2"), status: "completed", duration: 60 } });
165
+
166
+ await waitFor(() => events.some(e => e.type === "run:completed"), 3000);
167
+
168
+ // Verify event flow
169
+ const types = events.map(e => e.type);
170
+ expect(types).toContain("planning:started");
171
+ expect(types).toContain("planning:completed");
172
+ expect(types).toContain("task:dispatched");
173
+ expect(types).toContain("run:completed");
174
+
175
+ dispatcher.stop();
176
+ }, 15_000);
177
+
178
+ test("error handling: Claude failure emits planning:failed", async () => {
179
+ const config = createMockConfig();
180
+
181
+ mockProvider.mockResponse = {
182
+ result: "API Error",
183
+ exitCode: 1,
184
+ model: "claude-sonnet-4-5",
185
+ effortLevel: "medium",
186
+ duration: 50,
187
+ };
188
+
189
+ const planningService = new PlanningService(mockProvider, eventBus, config, logger, { fileChecker: mockFileChecker });
190
+
191
+ const events = collectEvents(eventBus, "planning:started", "planning:failed");
192
+
193
+ await expect(
194
+ planningService.planTasks({
195
+ runId: createRunId("e2e-err"),
196
+ parentBranch: "main",
197
+ requirementsPath: "/fake/req.md",
198
+ targetDocsDir: "/fake/docs",
199
+ })
200
+ ).rejects.toThrow();
201
+
202
+ expect(events.some(e => e.type === "planning:failed")).toBe(true);
203
+ const failedEvent = events.find(e => e.type === "planning:failed") as Extract<AADEvent, { type: "planning:failed" }>;
204
+ expect(failedEvent.error).toContain("exit code 1");
205
+ }, 15_000);
206
+
207
+ test("task dependency: task-2 dispatched only after task-1 completes", async () => {
208
+ const config = createMockConfig();
209
+ const stores = createStores("memory");
210
+
211
+ // Plan with dependency: task-2 depends on task-1
212
+ mockProvider.mockResponse = {
213
+ result: JSON.stringify({
214
+ run_id: "e2e-dep",
215
+ parent_branch: "main",
216
+ tasks: [
217
+ { task_id: "task-1", title: "Task 1", description: "First", files_to_modify: ["a.ts"], depends_on: [], priority: 1 },
218
+ { task_id: "task-2", title: "Task 2", description: "Second", files_to_modify: ["b.ts"], depends_on: ["task-1"], priority: 2 },
219
+ ],
220
+ }),
221
+ exitCode: 0,
222
+ model: "claude-sonnet-4-5",
223
+ effortLevel: "medium",
224
+ duration: 100,
225
+ };
226
+
227
+ const planningService = new PlanningService(mockProvider, eventBus, config, logger, { fileChecker: mockFileChecker });
228
+ const taskPlan = await planningService.planTasks({
229
+ runId: createRunId("e2e-dep"),
230
+ parentBranch: "main",
231
+ requirementsPath: "/fake/req.md",
232
+ targetDocsDir: "/fake/docs",
233
+ });
234
+
235
+ // Set up workers
236
+ await stores.workerStore.save({ workerId: createWorkerId("w-1"), status: "idle", currentTask: null });
237
+ await stores.workerStore.save({ workerId: createWorkerId("w-2"), status: "idle", currentTask: null });
238
+
239
+ const dispatchedTasks: TaskId[] = [];
240
+ eventBus.on("task:dispatched", (e: AADEvent) => {
241
+ if (e.type === "task:dispatched") dispatchedTasks.push(e.taskId);
242
+ });
243
+
244
+ const dispatcher = new Dispatcher({
245
+ taskStore: stores.taskStore,
246
+ workerStore: stores.workerStore,
247
+ runStore: stores.runStore,
248
+ eventBus,
249
+ config: { maxRetries: 0 },
250
+ logger,
251
+ });
252
+
253
+ await dispatcher.initialize(taskPlan);
254
+ dispatcher.start();
255
+
256
+ // Wait for first dispatch
257
+ await waitFor(() => dispatchedTasks.length >= 1, 3000);
258
+
259
+ // Only task-1 should be dispatched (task-2 blocked by dependency)
260
+ expect(dispatchedTasks).toHaveLength(1);
261
+ expect(dispatchedTasks[0]).toBe(createTaskId("task-1"));
262
+
263
+ // Re-add worker as idle (it was marked busy)
264
+ await stores.workerStore.save({ workerId: createWorkerId("w-1"), status: "idle", currentTask: null });
265
+
266
+ // Complete task-1 → should unblock task-2
267
+ eventBus.emit({
268
+ type: "task:completed",
269
+ taskId: createTaskId("task-1"),
270
+ result: { taskId: createTaskId("task-1"), status: "completed", duration: 50 },
271
+ });
272
+
273
+ await waitFor(() => dispatchedTasks.length >= 2, 3000);
274
+
275
+ expect(dispatchedTasks[1]).toBe(createTaskId("task-2"));
276
+
277
+ dispatcher.stop();
278
+ }, 15_000);
279
+ });