mcp-agent-foundry 1.0.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 (315) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +477 -0
  3. package/dist/cli/install-skills.d.ts +11 -0
  4. package/dist/cli/install-skills.d.ts.map +1 -0
  5. package/dist/cli/install-skills.js +143 -0
  6. package/dist/cli/install-skills.js.map +1 -0
  7. package/dist/cli/recovery-commands.d.ts +41 -0
  8. package/dist/cli/recovery-commands.d.ts.map +1 -0
  9. package/dist/cli/recovery-commands.js +241 -0
  10. package/dist/cli/recovery-commands.js.map +1 -0
  11. package/dist/cli/setup-wizard.d.ts +25 -0
  12. package/dist/cli/setup-wizard.d.ts.map +1 -0
  13. package/dist/cli/setup-wizard.js +1417 -0
  14. package/dist/cli/setup-wizard.js.map +1 -0
  15. package/dist/cli/test-connection.d.ts +45 -0
  16. package/dist/cli/test-connection.d.ts.map +1 -0
  17. package/dist/cli/test-connection.js +317 -0
  18. package/dist/cli/test-connection.js.map +1 -0
  19. package/dist/cli.d.ts +75 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +704 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/config/defaults.d.ts +57 -0
  24. package/dist/config/defaults.d.ts.map +1 -0
  25. package/dist/config/defaults.js +99 -0
  26. package/dist/config/defaults.js.map +1 -0
  27. package/dist/config/index.d.ts +14 -0
  28. package/dist/config/index.d.ts.map +1 -0
  29. package/dist/config/index.js +22 -0
  30. package/dist/config/index.js.map +1 -0
  31. package/dist/config/manager.d.ts +184 -0
  32. package/dist/config/manager.d.ts.map +1 -0
  33. package/dist/config/manager.js +347 -0
  34. package/dist/config/manager.js.map +1 -0
  35. package/dist/config/merger.d.ts +76 -0
  36. package/dist/config/merger.d.ts.map +1 -0
  37. package/dist/config/merger.js +189 -0
  38. package/dist/config/merger.js.map +1 -0
  39. package/dist/config/schema.d.ts +20 -0
  40. package/dist/config/schema.d.ts.map +1 -0
  41. package/dist/config/schema.js +20 -0
  42. package/dist/config/schema.js.map +1 -0
  43. package/dist/config/validator.d.ts +254 -0
  44. package/dist/config/validator.d.ts.map +1 -0
  45. package/dist/config/validator.js +363 -0
  46. package/dist/config/validator.js.map +1 -0
  47. package/dist/config/worktree-defaults.d.ts +23 -0
  48. package/dist/config/worktree-defaults.d.ts.map +1 -0
  49. package/dist/config/worktree-defaults.js +78 -0
  50. package/dist/config/worktree-defaults.js.map +1 -0
  51. package/dist/index.d.ts +8 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +44 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/mcp/tools/compare-agents.d.ts +25 -0
  56. package/dist/mcp/tools/compare-agents.d.ts.map +1 -0
  57. package/dist/mcp/tools/compare-agents.js +177 -0
  58. package/dist/mcp/tools/compare-agents.js.map +1 -0
  59. package/dist/mcp/tools/critique-plan.d.ts +26 -0
  60. package/dist/mcp/tools/critique-plan.d.ts.map +1 -0
  61. package/dist/mcp/tools/critique-plan.js +162 -0
  62. package/dist/mcp/tools/critique-plan.js.map +1 -0
  63. package/dist/mcp/tools/design-feedback.d.ts +26 -0
  64. package/dist/mcp/tools/design-feedback.d.ts.map +1 -0
  65. package/dist/mcp/tools/design-feedback.js +216 -0
  66. package/dist/mcp/tools/design-feedback.js.map +1 -0
  67. package/dist/mcp/tools/index.d.ts +50 -0
  68. package/dist/mcp/tools/index.d.ts.map +1 -0
  69. package/dist/mcp/tools/index.js +191 -0
  70. package/dist/mcp/tools/index.js.map +1 -0
  71. package/dist/mcp/tools/invoke-agent.d.ts +25 -0
  72. package/dist/mcp/tools/invoke-agent.d.ts.map +1 -0
  73. package/dist/mcp/tools/invoke-agent.js +141 -0
  74. package/dist/mcp/tools/invoke-agent.js.map +1 -0
  75. package/dist/mcp/tools/review-code.d.ts +25 -0
  76. package/dist/mcp/tools/review-code.d.ts.map +1 -0
  77. package/dist/mcp/tools/review-code.js +170 -0
  78. package/dist/mcp/tools/review-code.js.map +1 -0
  79. package/dist/mcp/tools/tasks/claim-next-task.d.ts +22 -0
  80. package/dist/mcp/tools/tasks/claim-next-task.d.ts.map +1 -0
  81. package/dist/mcp/tools/tasks/claim-next-task.js +203 -0
  82. package/dist/mcp/tools/tasks/claim-next-task.js.map +1 -0
  83. package/dist/mcp/tools/tasks/create-routed-task.d.ts +17 -0
  84. package/dist/mcp/tools/tasks/create-routed-task.d.ts.map +1 -0
  85. package/dist/mcp/tools/tasks/create-routed-task.js +178 -0
  86. package/dist/mcp/tools/tasks/create-routed-task.js.map +1 -0
  87. package/dist/mcp/tools/tasks/execute-pipeline.d.ts +22 -0
  88. package/dist/mcp/tools/tasks/execute-pipeline.d.ts.map +1 -0
  89. package/dist/mcp/tools/tasks/execute-pipeline.js +401 -0
  90. package/dist/mcp/tools/tasks/execute-pipeline.js.map +1 -0
  91. package/dist/mcp/tools/tasks/execute-task.d.ts +32 -0
  92. package/dist/mcp/tools/tasks/execute-task.d.ts.map +1 -0
  93. package/dist/mcp/tools/tasks/execute-task.js +284 -0
  94. package/dist/mcp/tools/tasks/execute-task.js.map +1 -0
  95. package/dist/mcp/tools/tasks/get-pipeline-status.d.ts +26 -0
  96. package/dist/mcp/tools/tasks/get-pipeline-status.d.ts.map +1 -0
  97. package/dist/mcp/tools/tasks/get-pipeline-status.js +460 -0
  98. package/dist/mcp/tools/tasks/get-pipeline-status.js.map +1 -0
  99. package/dist/mcp/tools/tasks/index.d.ts +36 -0
  100. package/dist/mcp/tools/tasks/index.d.ts.map +1 -0
  101. package/dist/mcp/tools/tasks/index.js +66 -0
  102. package/dist/mcp/tools/tasks/index.js.map +1 -0
  103. package/dist/mcp/tools/worktree/cleanup-worktrees.d.ts +17 -0
  104. package/dist/mcp/tools/worktree/cleanup-worktrees.d.ts.map +1 -0
  105. package/dist/mcp/tools/worktree/cleanup-worktrees.js +147 -0
  106. package/dist/mcp/tools/worktree/cleanup-worktrees.js.map +1 -0
  107. package/dist/mcp/tools/worktree/get-worktree-status.d.ts +17 -0
  108. package/dist/mcp/tools/worktree/get-worktree-status.d.ts.map +1 -0
  109. package/dist/mcp/tools/worktree/get-worktree-status.js +123 -0
  110. package/dist/mcp/tools/worktree/get-worktree-status.js.map +1 -0
  111. package/dist/mcp/tools/worktree/index.d.ts +41 -0
  112. package/dist/mcp/tools/worktree/index.d.ts.map +1 -0
  113. package/dist/mcp/tools/worktree/index.js +69 -0
  114. package/dist/mcp/tools/worktree/index.js.map +1 -0
  115. package/dist/mcp/tools/worktree/list-worktrees.d.ts +17 -0
  116. package/dist/mcp/tools/worktree/list-worktrees.d.ts.map +1 -0
  117. package/dist/mcp/tools/worktree/list-worktrees.js +136 -0
  118. package/dist/mcp/tools/worktree/list-worktrees.js.map +1 -0
  119. package/dist/mcp/tools/worktree/resolve-conflicts.d.ts +19 -0
  120. package/dist/mcp/tools/worktree/resolve-conflicts.d.ts.map +1 -0
  121. package/dist/mcp/tools/worktree/resolve-conflicts.js +228 -0
  122. package/dist/mcp/tools/worktree/resolve-conflicts.js.map +1 -0
  123. package/dist/mcp/transport/stdio.d.ts +13 -0
  124. package/dist/mcp/transport/stdio.d.ts.map +1 -0
  125. package/dist/mcp/transport/stdio.js +15 -0
  126. package/dist/mcp/transport/stdio.js.map +1 -0
  127. package/dist/observability/logger.d.ts +137 -0
  128. package/dist/observability/logger.d.ts.map +1 -0
  129. package/dist/observability/logger.js +235 -0
  130. package/dist/observability/logger.js.map +1 -0
  131. package/dist/observability/metrics.d.ts +250 -0
  132. package/dist/observability/metrics.d.ts.map +1 -0
  133. package/dist/observability/metrics.js +364 -0
  134. package/dist/observability/metrics.js.map +1 -0
  135. package/dist/persistence/index.d.ts +9 -0
  136. package/dist/persistence/index.d.ts.map +1 -0
  137. package/dist/persistence/index.js +9 -0
  138. package/dist/persistence/index.js.map +1 -0
  139. package/dist/persistence/state-schema.d.ts +116 -0
  140. package/dist/persistence/state-schema.d.ts.map +1 -0
  141. package/dist/persistence/state-schema.js +28 -0
  142. package/dist/persistence/state-schema.js.map +1 -0
  143. package/dist/persistence/state-store.d.ts +111 -0
  144. package/dist/persistence/state-store.d.ts.map +1 -0
  145. package/dist/persistence/state-store.js +291 -0
  146. package/dist/persistence/state-store.js.map +1 -0
  147. package/dist/providers/anthropic.d.ts +164 -0
  148. package/dist/providers/anthropic.d.ts.map +1 -0
  149. package/dist/providers/anthropic.js +500 -0
  150. package/dist/providers/anthropic.js.map +1 -0
  151. package/dist/providers/base.d.ts +151 -0
  152. package/dist/providers/base.d.ts.map +1 -0
  153. package/dist/providers/base.js +227 -0
  154. package/dist/providers/base.js.map +1 -0
  155. package/dist/providers/gemini.d.ts +85 -0
  156. package/dist/providers/gemini.d.ts.map +1 -0
  157. package/dist/providers/gemini.js +414 -0
  158. package/dist/providers/gemini.js.map +1 -0
  159. package/dist/providers/kimi.d.ts +19 -0
  160. package/dist/providers/kimi.d.ts.map +1 -0
  161. package/dist/providers/kimi.js +20 -0
  162. package/dist/providers/kimi.js.map +1 -0
  163. package/dist/providers/manager.d.ts +160 -0
  164. package/dist/providers/manager.d.ts.map +1 -0
  165. package/dist/providers/manager.js +264 -0
  166. package/dist/providers/manager.js.map +1 -0
  167. package/dist/providers/ollama.d.ts +83 -0
  168. package/dist/providers/ollama.d.ts.map +1 -0
  169. package/dist/providers/ollama.js +453 -0
  170. package/dist/providers/ollama.js.map +1 -0
  171. package/dist/providers/openai.d.ts +96 -0
  172. package/dist/providers/openai.d.ts.map +1 -0
  173. package/dist/providers/openai.js +457 -0
  174. package/dist/providers/openai.js.map +1 -0
  175. package/dist/providers/zai.d.ts +19 -0
  176. package/dist/providers/zai.d.ts.map +1 -0
  177. package/dist/providers/zai.js +20 -0
  178. package/dist/providers/zai.js.map +1 -0
  179. package/dist/router/context-manager.d.ts +2 -0
  180. package/dist/router/context-manager.d.ts.map +1 -0
  181. package/dist/router/context-manager.js +3 -0
  182. package/dist/router/context-manager.js.map +1 -0
  183. package/dist/router/engine.d.ts +169 -0
  184. package/dist/router/engine.d.ts.map +1 -0
  185. package/dist/router/engine.js +435 -0
  186. package/dist/router/engine.js.map +1 -0
  187. package/dist/router/pattern-executor.d.ts +317 -0
  188. package/dist/router/pattern-executor.d.ts.map +1 -0
  189. package/dist/router/pattern-executor.js +571 -0
  190. package/dist/router/pattern-executor.js.map +1 -0
  191. package/dist/router/role-resolver.d.ts +59 -0
  192. package/dist/router/role-resolver.d.ts.map +1 -0
  193. package/dist/router/role-resolver.js +95 -0
  194. package/dist/router/role-resolver.js.map +1 -0
  195. package/dist/server.d.ts +32 -0
  196. package/dist/server.d.ts.map +1 -0
  197. package/dist/server.js +223 -0
  198. package/dist/server.js.map +1 -0
  199. package/dist/startup.d.ts +78 -0
  200. package/dist/startup.d.ts.map +1 -0
  201. package/dist/startup.js +107 -0
  202. package/dist/startup.js.map +1 -0
  203. package/dist/tasks/coordinator.d.ts +141 -0
  204. package/dist/tasks/coordinator.d.ts.map +1 -0
  205. package/dist/tasks/coordinator.js +331 -0
  206. package/dist/tasks/coordinator.js.map +1 -0
  207. package/dist/tasks/index.d.ts +13 -0
  208. package/dist/tasks/index.d.ts.map +1 -0
  209. package/dist/tasks/index.js +13 -0
  210. package/dist/tasks/index.js.map +1 -0
  211. package/dist/tasks/persistent-state-coordinator.d.ts +89 -0
  212. package/dist/tasks/persistent-state-coordinator.d.ts.map +1 -0
  213. package/dist/tasks/persistent-state-coordinator.js +371 -0
  214. package/dist/tasks/persistent-state-coordinator.js.map +1 -0
  215. package/dist/tasks/pipeline-manager.d.ts +103 -0
  216. package/dist/tasks/pipeline-manager.d.ts.map +1 -0
  217. package/dist/tasks/pipeline-manager.js +358 -0
  218. package/dist/tasks/pipeline-manager.js.map +1 -0
  219. package/dist/tasks/state-coordinator.d.ts +79 -0
  220. package/dist/tasks/state-coordinator.d.ts.map +1 -0
  221. package/dist/tasks/state-coordinator.js +200 -0
  222. package/dist/tasks/state-coordinator.js.map +1 -0
  223. package/dist/tasks/worker-mode.d.ts +65 -0
  224. package/dist/tasks/worker-mode.d.ts.map +1 -0
  225. package/dist/tasks/worker-mode.js +208 -0
  226. package/dist/tasks/worker-mode.js.map +1 -0
  227. package/dist/translation/errors.d.ts +203 -0
  228. package/dist/translation/errors.d.ts.map +1 -0
  229. package/dist/translation/errors.js +477 -0
  230. package/dist/translation/errors.js.map +1 -0
  231. package/dist/translation/index.d.ts +12 -0
  232. package/dist/translation/index.d.ts.map +1 -0
  233. package/dist/translation/index.js +32 -0
  234. package/dist/translation/index.js.map +1 -0
  235. package/dist/translation/messages.d.ts +295 -0
  236. package/dist/translation/messages.d.ts.map +1 -0
  237. package/dist/translation/messages.js +557 -0
  238. package/dist/translation/messages.js.map +1 -0
  239. package/dist/translation/streaming.d.ts +226 -0
  240. package/dist/translation/streaming.d.ts.map +1 -0
  241. package/dist/translation/streaming.js +520 -0
  242. package/dist/translation/streaming.js.map +1 -0
  243. package/dist/translation/tools.d.ts +209 -0
  244. package/dist/translation/tools.d.ts.map +1 -0
  245. package/dist/translation/tools.js +331 -0
  246. package/dist/translation/tools.js.map +1 -0
  247. package/dist/types.d.ts +747 -0
  248. package/dist/types.d.ts.map +1 -0
  249. package/dist/types.js +86 -0
  250. package/dist/types.js.map +1 -0
  251. package/dist/utils/circuit-breaker.d.ts +175 -0
  252. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  253. package/dist/utils/circuit-breaker.js +315 -0
  254. package/dist/utils/circuit-breaker.js.map +1 -0
  255. package/dist/utils/env.d.ts +2 -0
  256. package/dist/utils/env.d.ts.map +1 -0
  257. package/dist/utils/env.js +3 -0
  258. package/dist/utils/env.js.map +1 -0
  259. package/dist/utils/git.d.ts +58 -0
  260. package/dist/utils/git.d.ts.map +1 -0
  261. package/dist/utils/git.js +197 -0
  262. package/dist/utils/git.js.map +1 -0
  263. package/dist/utils/index.d.ts +9 -0
  264. package/dist/utils/index.d.ts.map +1 -0
  265. package/dist/utils/index.js +9 -0
  266. package/dist/utils/index.js.map +1 -0
  267. package/dist/utils/merge-ordering.d.ts +45 -0
  268. package/dist/utils/merge-ordering.d.ts.map +1 -0
  269. package/dist/utils/merge-ordering.js +128 -0
  270. package/dist/utils/merge-ordering.js.map +1 -0
  271. package/dist/utils/retry.d.ts +106 -0
  272. package/dist/utils/retry.d.ts.map +1 -0
  273. package/dist/utils/retry.js +188 -0
  274. package/dist/utils/retry.js.map +1 -0
  275. package/dist/worktrees/branch-manager.d.ts +55 -0
  276. package/dist/worktrees/branch-manager.d.ts.map +1 -0
  277. package/dist/worktrees/branch-manager.js +129 -0
  278. package/dist/worktrees/branch-manager.js.map +1 -0
  279. package/dist/worktrees/conflict-handler.d.ts +72 -0
  280. package/dist/worktrees/conflict-handler.d.ts.map +1 -0
  281. package/dist/worktrees/conflict-handler.js +287 -0
  282. package/dist/worktrees/conflict-handler.js.map +1 -0
  283. package/dist/worktrees/conflict-parser.d.ts +28 -0
  284. package/dist/worktrees/conflict-parser.d.ts.map +1 -0
  285. package/dist/worktrees/conflict-parser.js +140 -0
  286. package/dist/worktrees/conflict-parser.js.map +1 -0
  287. package/dist/worktrees/index.d.ts +20 -0
  288. package/dist/worktrees/index.d.ts.map +1 -0
  289. package/dist/worktrees/index.js +20 -0
  290. package/dist/worktrees/index.js.map +1 -0
  291. package/dist/worktrees/instructions.d.ts +20 -0
  292. package/dist/worktrees/instructions.d.ts.map +1 -0
  293. package/dist/worktrees/instructions.js +84 -0
  294. package/dist/worktrees/instructions.js.map +1 -0
  295. package/dist/worktrees/manager.d.ts +76 -0
  296. package/dist/worktrees/manager.d.ts.map +1 -0
  297. package/dist/worktrees/manager.js +277 -0
  298. package/dist/worktrees/manager.js.map +1 -0
  299. package/dist/worktrees/pipeline-merge-orchestrator.d.ts +55 -0
  300. package/dist/worktrees/pipeline-merge-orchestrator.d.ts.map +1 -0
  301. package/dist/worktrees/pipeline-merge-orchestrator.js +221 -0
  302. package/dist/worktrees/pipeline-merge-orchestrator.js.map +1 -0
  303. package/dist/worktrees/pool.d.ts +95 -0
  304. package/dist/worktrees/pool.d.ts.map +1 -0
  305. package/dist/worktrees/pool.js +271 -0
  306. package/dist/worktrees/pool.js.map +1 -0
  307. package/dist/worktrees/recovery.d.ts +94 -0
  308. package/dist/worktrees/recovery.d.ts.map +1 -0
  309. package/dist/worktrees/recovery.js +371 -0
  310. package/dist/worktrees/recovery.js.map +1 -0
  311. package/dist/worktrees/resource-manager.d.ts +74 -0
  312. package/dist/worktrees/resource-manager.d.ts.map +1 -0
  313. package/dist/worktrees/resource-manager.js +228 -0
  314. package/dist/worktrees/resource-manager.js.map +1 -0
  315. package/package.json +88 -0
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Recovery Manager
3
+ *
4
+ * Handles startup recovery by reconciling persisted state with physical worktrees.
5
+ * Detects orphans, unlocks stuck worktrees, and cleans up abandoned resources.
6
+ */
7
+ import { simpleGit } from 'simple-git';
8
+ import path from 'path';
9
+ import { promises as fs } from 'fs';
10
+ import { createLogger } from '../observability/logger.js';
11
+ const DEFAULT_OPTIONS = {
12
+ autoCleanOrphans: false,
13
+ maxStaleAgeMs: 24 * 60 * 60 * 1000, // 24 hours
14
+ preserveUncommittedChanges: true,
15
+ dryRun: false,
16
+ };
17
+ // ============================================================================
18
+ // Recovery Manager
19
+ // ============================================================================
20
+ export class RecoveryManager {
21
+ repoPath;
22
+ worktreeBaseDir;
23
+ branchPattern;
24
+ git;
25
+ logger;
26
+ constructor(repoPath, worktreeBaseDir = '.agent-foundry/worktrees', branchPattern = 'task/') {
27
+ this.repoPath = repoPath;
28
+ this.worktreeBaseDir = worktreeBaseDir;
29
+ this.branchPattern = new RegExp(`^${branchPattern}`);
30
+ this.git = simpleGit(repoPath);
31
+ this.logger = createLogger({ name: 'recovery-manager' });
32
+ }
33
+ /**
34
+ * Main recovery entry point - call on server startup
35
+ */
36
+ async recoverOnStartup(persistedState, options = {}) {
37
+ const opts = { ...DEFAULT_OPTIONS, ...options };
38
+ this.logger.info('Starting recovery process', { dryRun: opts.dryRun });
39
+ const result = {
40
+ orphanedWorktrees: [],
41
+ orphanedTasks: [],
42
+ orphanedBranches: [],
43
+ recoveredWorktrees: [],
44
+ recoveredTasks: [],
45
+ stuckWorktrees: [],
46
+ cleanedUp: [],
47
+ errors: [],
48
+ };
49
+ try {
50
+ // Step 1: Discover physical state
51
+ const physicalWorktrees = await this.discoverPhysicalWorktrees();
52
+ const taskBranches = await this.discoverTaskBranches();
53
+ this.logger.info('Discovered physical state', {
54
+ physicalWorktrees: physicalWorktrees.size,
55
+ taskBranches: taskBranches.size,
56
+ persistedWorktrees: persistedState?.worktrees.length ?? 0,
57
+ persistedTasks: persistedState?.tasks.length ?? 0,
58
+ });
59
+ // Step 2: Reconcile if we have persisted state
60
+ if (persistedState) {
61
+ await this.reconcileWithPersistedState(persistedState, physicalWorktrees, taskBranches, result, opts);
62
+ }
63
+ else {
64
+ // No persisted state - all physical worktrees are orphans
65
+ await this.handleNoPersistedState(physicalWorktrees, taskBranches, result, opts);
66
+ }
67
+ // Step 3: Auto-cleanup if enabled
68
+ if (opts.autoCleanOrphans && !opts.dryRun) {
69
+ await this.cleanupOrphans(result, opts);
70
+ }
71
+ this.logger.info('Recovery complete', {
72
+ orphanedWorktrees: result.orphanedWorktrees.length,
73
+ orphanedTasks: result.orphanedTasks.length,
74
+ orphanedBranches: result.orphanedBranches.length,
75
+ recovered: result.recoveredWorktrees.length + result.recoveredTasks.length,
76
+ cleanedUp: result.cleanedUp.length,
77
+ errors: result.errors.length,
78
+ });
79
+ }
80
+ catch (error) {
81
+ const err = error instanceof Error ? error : new Error(String(error));
82
+ this.logger.error('Recovery failed', { error: err });
83
+ result.errors.push({
84
+ resource: 'recovery',
85
+ error: err.message,
86
+ });
87
+ }
88
+ return result;
89
+ }
90
+ /**
91
+ * Discover all physical worktrees in the worktree directory
92
+ */
93
+ async discoverPhysicalWorktrees() {
94
+ const worktrees = new Map();
95
+ const fullWorktreeDir = path.join(this.repoPath, this.worktreeBaseDir);
96
+ try {
97
+ const entries = await fs.readdir(fullWorktreeDir, { withFileTypes: true });
98
+ for (const entry of entries) {
99
+ if (!entry.isDirectory())
100
+ continue;
101
+ const worktreePath = path.join(fullWorktreeDir, entry.name);
102
+ try {
103
+ const info = await this.getPhysicalWorktreeInfo(entry.name, worktreePath);
104
+ worktrees.set(entry.name, info);
105
+ }
106
+ catch (error) {
107
+ this.logger.warn('Failed to inspect worktree', { worktree: entry.name, error });
108
+ }
109
+ }
110
+ }
111
+ catch (error) {
112
+ if (error.code !== 'ENOENT') {
113
+ throw error;
114
+ }
115
+ // Directory doesn't exist - no worktrees
116
+ }
117
+ return worktrees;
118
+ }
119
+ async getPhysicalWorktreeInfo(id, worktreePath) {
120
+ const worktreeGit = simpleGit(worktreePath);
121
+ let branch = '';
122
+ let hasUncommittedChanges = false;
123
+ let lastCommitDate;
124
+ try {
125
+ const branchResult = await worktreeGit.revparse(['--abbrev-ref', 'HEAD']);
126
+ branch = branchResult.trim();
127
+ const status = await worktreeGit.status();
128
+ hasUncommittedChanges = !status.isClean();
129
+ const log = await worktreeGit.log(['-1', '--format=%ci']);
130
+ if (log.latest) {
131
+ lastCommitDate = new Date(log.latest.date);
132
+ }
133
+ }
134
+ catch (error) {
135
+ this.logger.debug('Failed to get worktree git info', { id, error });
136
+ }
137
+ return {
138
+ id,
139
+ path: worktreePath,
140
+ branch,
141
+ hasUncommittedChanges,
142
+ lastCommitDate,
143
+ };
144
+ }
145
+ /**
146
+ * Discover all task branches in the repository
147
+ */
148
+ async discoverTaskBranches() {
149
+ const branches = new Map();
150
+ try {
151
+ const branchList = await this.git.branch(['-a']);
152
+ for (const branchName of branchList.all) {
153
+ // Skip remote tracking branches for now
154
+ if (branchName.startsWith('remotes/'))
155
+ continue;
156
+ if (this.branchPattern.test(branchName)) {
157
+ try {
158
+ const log = await this.git.log(['-1', '--format=%ci', branchName]);
159
+ branches.set(branchName, {
160
+ name: branchName,
161
+ lastCommitDate: log.latest ? new Date(log.latest.date) : undefined,
162
+ });
163
+ }
164
+ catch {
165
+ branches.set(branchName, { name: branchName });
166
+ }
167
+ }
168
+ }
169
+ }
170
+ catch (error) {
171
+ this.logger.warn('Failed to list branches', { error });
172
+ }
173
+ return branches;
174
+ }
175
+ /**
176
+ * Reconcile persisted state with physical reality
177
+ */
178
+ async reconcileWithPersistedState(state, physicalWorktrees, taskBranches, result, _options) {
179
+ const persistedWorktreeIds = new Set(state.worktrees.map((w) => w.id));
180
+ // Check persisted worktrees against physical state
181
+ for (const persistedWorktree of state.worktrees) {
182
+ const physical = physicalWorktrees.get(persistedWorktree.id);
183
+ if (!physical) {
184
+ // Persisted worktree no longer exists physically
185
+ if (persistedWorktree.taskId) {
186
+ const task = state.tasks.find((t) => t.taskId === persistedWorktree.taskId);
187
+ result.orphanedTasks.push({
188
+ taskId: persistedWorktree.taskId,
189
+ role: task?.role ?? 'unknown',
190
+ status: task?.status ?? 'unknown',
191
+ reason: 'worktree_missing',
192
+ worktreeId: persistedWorktree.id,
193
+ });
194
+ }
195
+ continue;
196
+ }
197
+ // Check for stuck states
198
+ if (this.isStuckState(persistedWorktree.status)) {
199
+ result.stuckWorktrees.push(persistedWorktree.id);
200
+ }
201
+ // Worktree exists - mark as recovered
202
+ result.recoveredWorktrees.push(persistedWorktree.id);
203
+ }
204
+ // Check physical worktrees not in persisted state
205
+ for (const [id, physical] of physicalWorktrees) {
206
+ if (!persistedWorktreeIds.has(id)) {
207
+ result.orphanedWorktrees.push({
208
+ id,
209
+ path: physical.path,
210
+ branch: physical.branch,
211
+ reason: 'unknown_state',
212
+ physicalExists: true,
213
+ branchExists: taskBranches.has(physical.branch),
214
+ hasUncommittedChanges: physical.hasUncommittedChanges,
215
+ });
216
+ }
217
+ }
218
+ // Check for orphaned branches
219
+ for (const [branchName, info] of taskBranches) {
220
+ const hasWorktree = Array.from(physicalWorktrees.values()).some((w) => w.branch === branchName);
221
+ if (!hasWorktree) {
222
+ result.orphanedBranches.push({
223
+ name: branchName,
224
+ reason: 'no_worktree',
225
+ lastCommitDate: info.lastCommitDate,
226
+ });
227
+ }
228
+ }
229
+ // Check persisted tasks for orphans
230
+ for (const task of state.tasks) {
231
+ if (task.worktreeId && !physicalWorktrees.has(task.worktreeId)) {
232
+ // Already handled above
233
+ continue;
234
+ }
235
+ if (task.status === 'running' && !task.worktreeId) {
236
+ result.orphanedTasks.push({
237
+ taskId: task.taskId,
238
+ role: task.role,
239
+ status: task.status,
240
+ reason: 'no_worktree',
241
+ });
242
+ }
243
+ }
244
+ }
245
+ /**
246
+ * Handle case where we have no persisted state
247
+ */
248
+ async handleNoPersistedState(physicalWorktrees, taskBranches, result, _options) {
249
+ this.logger.warn('No persisted state found - all physical worktrees are orphans');
250
+ // All physical worktrees are orphans
251
+ for (const [id, physical] of physicalWorktrees) {
252
+ result.orphanedWorktrees.push({
253
+ id,
254
+ path: physical.path,
255
+ branch: physical.branch,
256
+ reason: 'no_task',
257
+ physicalExists: true,
258
+ branchExists: taskBranches.has(physical.branch),
259
+ hasUncommittedChanges: physical.hasUncommittedChanges,
260
+ });
261
+ }
262
+ // All task branches without worktrees are orphans
263
+ for (const [branchName, info] of taskBranches) {
264
+ const hasWorktree = Array.from(physicalWorktrees.values()).some((w) => w.branch === branchName);
265
+ if (!hasWorktree) {
266
+ result.orphanedBranches.push({
267
+ name: branchName,
268
+ reason: 'no_worktree',
269
+ lastCommitDate: info.lastCommitDate,
270
+ });
271
+ }
272
+ }
273
+ }
274
+ isStuckState(status) {
275
+ // These are transitional states that shouldn't persist across restarts
276
+ return status === 'assigned' || status === 'completing';
277
+ }
278
+ /**
279
+ * Clean up orphaned resources
280
+ */
281
+ async cleanupOrphans(result, options) {
282
+ for (const orphan of result.orphanedWorktrees) {
283
+ if (options.preserveUncommittedChanges && orphan.hasUncommittedChanges) {
284
+ this.logger.info('Preserving orphan with uncommitted changes', { id: orphan.id });
285
+ continue;
286
+ }
287
+ try {
288
+ await this.removeWorktree(orphan.id, orphan.path, orphan.branch);
289
+ result.cleanedUp.push(orphan.id);
290
+ }
291
+ catch (error) {
292
+ result.errors.push({
293
+ resource: orphan.id,
294
+ error: error instanceof Error ? error.message : String(error),
295
+ });
296
+ }
297
+ }
298
+ for (const orphan of result.orphanedBranches) {
299
+ try {
300
+ await this.git.deleteLocalBranch(orphan.name, true);
301
+ result.cleanedUp.push(`branch:${orphan.name}`);
302
+ this.logger.info('Deleted orphan branch', { branch: orphan.name });
303
+ }
304
+ catch (error) {
305
+ result.errors.push({
306
+ resource: `branch:${orphan.name}`,
307
+ error: error instanceof Error ? error.message : String(error),
308
+ });
309
+ }
310
+ }
311
+ }
312
+ async removeWorktree(id, worktreePath, branch) {
313
+ this.logger.info('Removing orphan worktree', { id, branch });
314
+ // Remove the worktree
315
+ await this.git.raw(['worktree', 'remove', '--force', worktreePath]);
316
+ // Delete the branch
317
+ try {
318
+ await this.git.deleteLocalBranch(branch, true);
319
+ }
320
+ catch {
321
+ // Branch may already be deleted
322
+ }
323
+ }
324
+ /**
325
+ * Unlock worktrees stuck in transitional states
326
+ */
327
+ async unlockStuckWorktrees(stuckIds, worktrees) {
328
+ const unlocked = [];
329
+ for (const id of stuckIds) {
330
+ const worktree = worktrees.get(id);
331
+ if (!worktree)
332
+ continue;
333
+ // Reset to available if assigned, or stale if completing
334
+ const newStatus = worktree.status === 'assigned' ? 'available' : 'stale';
335
+ worktree.status = newStatus;
336
+ worktree.lastActivityAt = Date.now();
337
+ unlocked.push(id);
338
+ this.logger.info('Unlocked stuck worktree', {
339
+ id,
340
+ oldStatus: worktree.status,
341
+ newStatus,
342
+ });
343
+ }
344
+ return unlocked;
345
+ }
346
+ /**
347
+ * Prune worktrees that have been stale too long
348
+ */
349
+ async pruneStaleWorktrees(worktrees, maxAgeMs = DEFAULT_OPTIONS.maxStaleAgeMs) {
350
+ const now = Date.now();
351
+ const pruned = [];
352
+ for (const [id, worktree] of worktrees) {
353
+ if (worktree.status !== 'stale')
354
+ continue;
355
+ const age = now - worktree.lastActivityAt;
356
+ if (age > maxAgeMs) {
357
+ try {
358
+ await this.removeWorktree(id, worktree.path, worktree.branch);
359
+ worktrees.delete(id);
360
+ pruned.push(id);
361
+ }
362
+ catch (error) {
363
+ const err = error instanceof Error ? error : new Error(String(error));
364
+ this.logger.error('Failed to prune stale worktree', { id, error: err });
365
+ }
366
+ }
367
+ }
368
+ return pruned;
369
+ }
370
+ }
371
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/worktrees/recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Resource Manager
3
+ *
4
+ * Manages worktree resource limits including count, disk usage,
5
+ * stale detection, and automatic cleanup.
6
+ */
7
+ import type { WorktreeManager } from "./manager.js";
8
+ import type { ResourceLimits, ResourceUsage, WorktreeMetrics, ResourceReport, Worktree, WorktreeStatus } from "../types.js";
9
+ export declare class ResourceManager {
10
+ private readonly worktreeManager;
11
+ private readonly limits;
12
+ private readonly logger;
13
+ constructor(worktreeManager: WorktreeManager, limits?: Partial<ResourceLimits>);
14
+ /**
15
+ * Get current resource usage.
16
+ */
17
+ getCurrentUsage(): Promise<ResourceUsage>;
18
+ /**
19
+ * Check if a new worktree can be allocated.
20
+ */
21
+ canAllocate(): Promise<{
22
+ allowed: boolean;
23
+ reason?: string;
24
+ }>;
25
+ /**
26
+ * Get detailed metrics for all worktrees.
27
+ */
28
+ getAllWorktreeMetrics(): Promise<WorktreeMetrics[]>;
29
+ /**
30
+ * Get metrics for a specific worktree.
31
+ */
32
+ getWorktreeMetrics(worktreeId: string): Promise<WorktreeMetrics | null>;
33
+ /**
34
+ * Find stale worktrees (idle beyond threshold).
35
+ */
36
+ findStaleWorktrees(maxIdleTimeMs?: number): Worktree[];
37
+ /**
38
+ * Check if cleanup should be triggered.
39
+ */
40
+ shouldTriggerCleanup(): Promise<boolean>;
41
+ /**
42
+ * Cleanup stale worktrees.
43
+ */
44
+ cleanupStale(maxIdleTimeMs?: number): Promise<string[]>;
45
+ /**
46
+ * Cleanup worktrees by status.
47
+ */
48
+ cleanupByStatus(status: WorktreeStatus): Promise<string[]>;
49
+ /**
50
+ * Force cleanup specific worktrees.
51
+ */
52
+ forceCleanup(worktreeIds: string[]): Promise<{
53
+ cleaned: string[];
54
+ failed: string[];
55
+ }>;
56
+ /**
57
+ * Get full resource report.
58
+ */
59
+ getReport(): Promise<ResourceReport>;
60
+ /**
61
+ * Calculate disk usage for a path in MB.
62
+ *
63
+ * Note: Uses execSync with shell for the du command. The dirPath parameter
64
+ * is system-controlled (comes from WorktreeManager internal state) and is
65
+ * quoted to prevent any injection. This is safe as worktree paths are
66
+ * generated internally and not from user input.
67
+ */
68
+ private calculateDiskUsage;
69
+ /**
70
+ * Get the configured limits.
71
+ */
72
+ getLimits(): ResourceLimits;
73
+ }
74
+ //# sourceMappingURL=resource-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-manager.d.ts","sourceRoot":"","sources":["../../src/worktrees/resource-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,EACd,QAAQ,EACR,cAAc,EACf,MAAM,aAAa,CAAC;AASrB,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAGtB,eAAe,EAAE,eAAe,EAChC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAOlC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAuB/C;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAoBnE;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAoBzD;;OAEG;IACG,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAgB7E;;OAEG;IACH,kBAAkB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE;IAatD;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAK9C;;OAEG;IACG,YAAY,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAuB7D;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBhE;;OAEG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAoBnD;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAc1C;;;;;;;OAOG;YACW,kBAAkB;IAehC;;OAEG;IACH,SAAS,IAAI,cAAc;CAG5B"}