@aion0/forge 0.5.25 → 0.5.27

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 (2987) hide show
  1. package/.forge/memory/graph.json +1 -0
  2. package/.forge/memory/knowledge.json +18 -0
  3. package/.forge/memory/meta.json +7 -0
  4. package/.forge/worktrees/pipeline-0a33c50d/CLAUDE.md +86 -0
  5. package/.forge/worktrees/pipeline-0a33c50d/README.md +136 -0
  6. package/.forge/worktrees/pipeline-0a33c50d/RELEASE_NOTES.md +11 -0
  7. package/.forge/worktrees/pipeline-0a33c50d/app/api/agents/route.ts +17 -0
  8. package/.forge/worktrees/pipeline-0a33c50d/app/api/auth/[...nextauth]/route.ts +3 -0
  9. package/.forge/worktrees/pipeline-0a33c50d/app/api/auth/verify/route.ts +46 -0
  10. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude/[id]/route.ts +31 -0
  11. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude/[id]/stream/route.ts +63 -0
  12. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude/route.ts +28 -0
  13. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  14. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  15. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude-sessions/[projectName]/route.ts +37 -0
  16. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude-sessions/sync/route.ts +17 -0
  17. package/.forge/worktrees/pipeline-0a33c50d/app/api/claude-templates/route.ts +145 -0
  18. package/.forge/worktrees/pipeline-0a33c50d/app/api/code/route.ts +299 -0
  19. package/.forge/worktrees/pipeline-0a33c50d/app/api/delivery/[id]/route.ts +62 -0
  20. package/.forge/worktrees/pipeline-0a33c50d/app/api/delivery/route.ts +40 -0
  21. package/.forge/worktrees/pipeline-0a33c50d/app/api/detect-cli/route.ts +46 -0
  22. package/.forge/worktrees/pipeline-0a33c50d/app/api/docs/route.ts +176 -0
  23. package/.forge/worktrees/pipeline-0a33c50d/app/api/docs/sessions/route.ts +54 -0
  24. package/.forge/worktrees/pipeline-0a33c50d/app/api/favorites/route.ts +26 -0
  25. package/.forge/worktrees/pipeline-0a33c50d/app/api/flows/route.ts +6 -0
  26. package/.forge/worktrees/pipeline-0a33c50d/app/api/flows/run/route.ts +19 -0
  27. package/.forge/worktrees/pipeline-0a33c50d/app/api/git/route.ts +149 -0
  28. package/.forge/worktrees/pipeline-0a33c50d/app/api/help/route.ts +84 -0
  29. package/.forge/worktrees/pipeline-0a33c50d/app/api/issue-scanner/route.ts +116 -0
  30. package/.forge/worktrees/pipeline-0a33c50d/app/api/logs/route.ts +100 -0
  31. package/.forge/worktrees/pipeline-0a33c50d/app/api/mobile-chat/route.ts +115 -0
  32. package/.forge/worktrees/pipeline-0a33c50d/app/api/monitor/route.ts +74 -0
  33. package/.forge/worktrees/pipeline-0a33c50d/app/api/notifications/route.ts +42 -0
  34. package/.forge/worktrees/pipeline-0a33c50d/app/api/notify/test/route.ts +33 -0
  35. package/.forge/worktrees/pipeline-0a33c50d/app/api/online/route.ts +40 -0
  36. package/.forge/worktrees/pipeline-0a33c50d/app/api/pipelines/[id]/route.ts +41 -0
  37. package/.forge/worktrees/pipeline-0a33c50d/app/api/pipelines/route.ts +90 -0
  38. package/.forge/worktrees/pipeline-0a33c50d/app/api/plugins/route.ts +75 -0
  39. package/.forge/worktrees/pipeline-0a33c50d/app/api/preview/[...path]/route.ts +64 -0
  40. package/.forge/worktrees/pipeline-0a33c50d/app/api/preview/route.ts +156 -0
  41. package/.forge/worktrees/pipeline-0a33c50d/app/api/project-pipelines/route.ts +91 -0
  42. package/.forge/worktrees/pipeline-0a33c50d/app/api/project-sessions/route.ts +61 -0
  43. package/.forge/worktrees/pipeline-0a33c50d/app/api/projects/route.ts +26 -0
  44. package/.forge/worktrees/pipeline-0a33c50d/app/api/sessions/[id]/chat/route.ts +64 -0
  45. package/.forge/worktrees/pipeline-0a33c50d/app/api/sessions/[id]/messages/route.ts +9 -0
  46. package/.forge/worktrees/pipeline-0a33c50d/app/api/sessions/[id]/route.ts +17 -0
  47. package/.forge/worktrees/pipeline-0a33c50d/app/api/sessions/route.ts +20 -0
  48. package/.forge/worktrees/pipeline-0a33c50d/app/api/settings/route.ts +64 -0
  49. package/.forge/worktrees/pipeline-0a33c50d/app/api/skills/local/route.ts +228 -0
  50. package/.forge/worktrees/pipeline-0a33c50d/app/api/skills/route.ts +182 -0
  51. package/.forge/worktrees/pipeline-0a33c50d/app/api/smith-templates/route.ts +81 -0
  52. package/.forge/worktrees/pipeline-0a33c50d/app/api/status/route.ts +12 -0
  53. package/.forge/worktrees/pipeline-0a33c50d/app/api/tabs/route.ts +25 -0
  54. package/.forge/worktrees/pipeline-0a33c50d/app/api/tasks/[id]/route.ts +51 -0
  55. package/.forge/worktrees/pipeline-0a33c50d/app/api/tasks/[id]/stream/route.ts +77 -0
  56. package/.forge/worktrees/pipeline-0a33c50d/app/api/tasks/link/route.ts +37 -0
  57. package/.forge/worktrees/pipeline-0a33c50d/app/api/tasks/route.ts +44 -0
  58. package/.forge/worktrees/pipeline-0a33c50d/app/api/tasks/session/route.ts +14 -0
  59. package/.forge/worktrees/pipeline-0a33c50d/app/api/telegram/route.ts +23 -0
  60. package/.forge/worktrees/pipeline-0a33c50d/app/api/templates/route.ts +6 -0
  61. package/.forge/worktrees/pipeline-0a33c50d/app/api/terminal-bell/route.ts +35 -0
  62. package/.forge/worktrees/pipeline-0a33c50d/app/api/terminal-cwd/route.ts +19 -0
  63. package/.forge/worktrees/pipeline-0a33c50d/app/api/terminal-state/route.ts +15 -0
  64. package/.forge/worktrees/pipeline-0a33c50d/app/api/tunnel/route.ts +26 -0
  65. package/.forge/worktrees/pipeline-0a33c50d/app/api/upgrade/route.ts +43 -0
  66. package/.forge/worktrees/pipeline-0a33c50d/app/api/usage/route.ts +20 -0
  67. package/.forge/worktrees/pipeline-0a33c50d/app/api/version/route.ts +78 -0
  68. package/.forge/worktrees/pipeline-0a33c50d/app/api/watchers/route.ts +33 -0
  69. package/.forge/worktrees/pipeline-0a33c50d/app/api/workspace/[id]/agents/route.ts +35 -0
  70. package/.forge/worktrees/pipeline-0a33c50d/app/api/workspace/[id]/memory/route.ts +23 -0
  71. package/.forge/worktrees/pipeline-0a33c50d/app/api/workspace/[id]/smith/route.ts +22 -0
  72. package/.forge/worktrees/pipeline-0a33c50d/app/api/workspace/[id]/stream/route.ts +28 -0
  73. package/.forge/worktrees/pipeline-0a33c50d/app/api/workspace/route.ts +100 -0
  74. package/.forge/worktrees/pipeline-0a33c50d/app/global-error.tsx +21 -0
  75. package/.forge/worktrees/pipeline-0a33c50d/app/globals.css +52 -0
  76. package/.forge/worktrees/pipeline-0a33c50d/app/icon.ico +0 -0
  77. package/.forge/worktrees/pipeline-0a33c50d/app/icon.png +0 -0
  78. package/.forge/worktrees/pipeline-0a33c50d/app/icon.svg +106 -0
  79. package/.forge/worktrees/pipeline-0a33c50d/app/layout.tsx +17 -0
  80. package/.forge/worktrees/pipeline-0a33c50d/app/login/LoginForm.tsx +96 -0
  81. package/.forge/worktrees/pipeline-0a33c50d/app/login/page.tsx +10 -0
  82. package/.forge/worktrees/pipeline-0a33c50d/app/mobile/page.tsx +9 -0
  83. package/.forge/worktrees/pipeline-0a33c50d/app/page.tsx +21 -0
  84. package/.forge/worktrees/pipeline-0a33c50d/bin/forge-server.mjs +484 -0
  85. package/.forge/worktrees/pipeline-0a33c50d/check-forge-status.sh +71 -0
  86. package/.forge/worktrees/pipeline-0a33c50d/cli/mw.ts +579 -0
  87. package/.forge/worktrees/pipeline-0a33c50d/components/BrowserPanel.tsx +175 -0
  88. package/.forge/worktrees/pipeline-0a33c50d/components/ChatPanel.tsx +191 -0
  89. package/.forge/worktrees/pipeline-0a33c50d/components/ClaudeTerminal.tsx +267 -0
  90. package/.forge/worktrees/pipeline-0a33c50d/components/CodeViewer.tsx +787 -0
  91. package/.forge/worktrees/pipeline-0a33c50d/components/ConversationEditor.tsx +411 -0
  92. package/.forge/worktrees/pipeline-0a33c50d/components/ConversationGraphView.tsx +347 -0
  93. package/.forge/worktrees/pipeline-0a33c50d/components/ConversationTerminalView.tsx +303 -0
  94. package/.forge/worktrees/pipeline-0a33c50d/components/Dashboard.tsx +807 -0
  95. package/.forge/worktrees/pipeline-0a33c50d/components/DashboardWrapper.tsx +9 -0
  96. package/.forge/worktrees/pipeline-0a33c50d/components/DeliveryFlowEditor.tsx +491 -0
  97. package/.forge/worktrees/pipeline-0a33c50d/components/DeliveryList.tsx +230 -0
  98. package/.forge/worktrees/pipeline-0a33c50d/components/DeliveryWorkspace.tsx +589 -0
  99. package/.forge/worktrees/pipeline-0a33c50d/components/DocTerminal.tsx +187 -0
  100. package/.forge/worktrees/pipeline-0a33c50d/components/DocsViewer.tsx +574 -0
  101. package/.forge/worktrees/pipeline-0a33c50d/components/HelpDialog.tsx +169 -0
  102. package/.forge/worktrees/pipeline-0a33c50d/components/HelpTerminal.tsx +141 -0
  103. package/.forge/worktrees/pipeline-0a33c50d/components/InlinePipelineView.tsx +111 -0
  104. package/.forge/worktrees/pipeline-0a33c50d/components/LogViewer.tsx +194 -0
  105. package/.forge/worktrees/pipeline-0a33c50d/components/MarkdownContent.tsx +73 -0
  106. package/.forge/worktrees/pipeline-0a33c50d/components/MobileView.tsx +385 -0
  107. package/.forge/worktrees/pipeline-0a33c50d/components/MonitorPanel.tsx +122 -0
  108. package/.forge/worktrees/pipeline-0a33c50d/components/NewSessionModal.tsx +93 -0
  109. package/.forge/worktrees/pipeline-0a33c50d/components/NewTaskModal.tsx +492 -0
  110. package/.forge/worktrees/pipeline-0a33c50d/components/PipelineEditor.tsx +570 -0
  111. package/.forge/worktrees/pipeline-0a33c50d/components/PipelineView.tsx +1018 -0
  112. package/.forge/worktrees/pipeline-0a33c50d/components/PluginsPanel.tsx +472 -0
  113. package/.forge/worktrees/pipeline-0a33c50d/components/ProjectDetail.tsx +1618 -0
  114. package/.forge/worktrees/pipeline-0a33c50d/components/ProjectList.tsx +108 -0
  115. package/.forge/worktrees/pipeline-0a33c50d/components/ProjectManager.tsx +401 -0
  116. package/.forge/worktrees/pipeline-0a33c50d/components/SessionList.tsx +74 -0
  117. package/.forge/worktrees/pipeline-0a33c50d/components/SessionView.tsx +726 -0
  118. package/.forge/worktrees/pipeline-0a33c50d/components/SettingsModal.tsx +1647 -0
  119. package/.forge/worktrees/pipeline-0a33c50d/components/SkillsPanel.tsx +969 -0
  120. package/.forge/worktrees/pipeline-0a33c50d/components/StatusBar.tsx +99 -0
  121. package/.forge/worktrees/pipeline-0a33c50d/components/TabBar.tsx +46 -0
  122. package/.forge/worktrees/pipeline-0a33c50d/components/TaskBoard.tsx +113 -0
  123. package/.forge/worktrees/pipeline-0a33c50d/components/TaskDetail.tsx +372 -0
  124. package/.forge/worktrees/pipeline-0a33c50d/components/TerminalLauncher.tsx +398 -0
  125. package/.forge/worktrees/pipeline-0a33c50d/components/TunnelToggle.tsx +206 -0
  126. package/.forge/worktrees/pipeline-0a33c50d/components/UsagePanel.tsx +207 -0
  127. package/.forge/worktrees/pipeline-0a33c50d/components/WebTerminal.tsx +1683 -0
  128. package/.forge/worktrees/pipeline-0a33c50d/components/WorkspaceTree.tsx +221 -0
  129. package/.forge/worktrees/pipeline-0a33c50d/components/WorkspaceView.tsx +4048 -0
  130. package/.forge/worktrees/pipeline-0a33c50d/dev-test.sh +5 -0
  131. package/.forge/worktrees/pipeline-0a33c50d/docs/Forge_Memory_Layer_Design.docx +0 -0
  132. package/.forge/worktrees/pipeline-0a33c50d/docs/Forge_Strategy_Research_2026.docx +0 -0
  133. package/.forge/worktrees/pipeline-0a33c50d/docs/LOCAL-DEPLOY.md +144 -0
  134. package/.forge/worktrees/pipeline-0a33c50d/docs/roadmap-multi-agent-workflow.md +330 -0
  135. package/.forge/worktrees/pipeline-0a33c50d/forge-logo.png +0 -0
  136. package/.forge/worktrees/pipeline-0a33c50d/forge-logo.svg +106 -0
  137. package/.forge/worktrees/pipeline-0a33c50d/hooks/useSidebarResize.ts +52 -0
  138. package/.forge/worktrees/pipeline-0a33c50d/install.sh +29 -0
  139. package/.forge/worktrees/pipeline-0a33c50d/instrumentation.ts +35 -0
  140. package/.forge/worktrees/pipeline-0a33c50d/lib/agents/claude-adapter.ts +104 -0
  141. package/.forge/worktrees/pipeline-0a33c50d/lib/agents/generic-adapter.ts +64 -0
  142. package/.forge/worktrees/pipeline-0a33c50d/lib/agents/index.ts +245 -0
  143. package/.forge/worktrees/pipeline-0a33c50d/lib/agents/types.ts +70 -0
  144. package/.forge/worktrees/pipeline-0a33c50d/lib/artifacts.ts +106 -0
  145. package/.forge/worktrees/pipeline-0a33c50d/lib/auth.ts +62 -0
  146. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/docker.yaml +70 -0
  147. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/http.yaml +66 -0
  148. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/jenkins.yaml +92 -0
  149. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/llm-vision.yaml +85 -0
  150. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/playwright.yaml +111 -0
  151. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/shell-command.yaml +60 -0
  152. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/slack.yaml +48 -0
  153. package/.forge/worktrees/pipeline-0a33c50d/lib/builtin-plugins/webhook.yaml +56 -0
  154. package/.forge/worktrees/pipeline-0a33c50d/lib/claude-process.ts +352 -0
  155. package/.forge/worktrees/pipeline-0a33c50d/lib/claude-sessions.ts +266 -0
  156. package/.forge/worktrees/pipeline-0a33c50d/lib/claude-templates.ts +227 -0
  157. package/.forge/worktrees/pipeline-0a33c50d/lib/cloudflared.ts +424 -0
  158. package/.forge/worktrees/pipeline-0a33c50d/lib/crypto.ts +67 -0
  159. package/.forge/worktrees/pipeline-0a33c50d/lib/delivery.ts +787 -0
  160. package/.forge/worktrees/pipeline-0a33c50d/lib/dirs.ts +99 -0
  161. package/.forge/worktrees/pipeline-0a33c50d/lib/flows.ts +86 -0
  162. package/.forge/worktrees/pipeline-0a33c50d/lib/forge-mcp-server.ts +717 -0
  163. package/.forge/worktrees/pipeline-0a33c50d/lib/forge-skills/forge-inbox.md +38 -0
  164. package/.forge/worktrees/pipeline-0a33c50d/lib/forge-skills/forge-send.md +47 -0
  165. package/.forge/worktrees/pipeline-0a33c50d/lib/forge-skills/forge-status.md +32 -0
  166. package/.forge/worktrees/pipeline-0a33c50d/lib/forge-skills/forge-workspace-sync.md +37 -0
  167. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/00-overview.md +40 -0
  168. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/01-settings.md +194 -0
  169. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/02-telegram.md +41 -0
  170. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/03-tunnel.md +31 -0
  171. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/04-tasks.md +52 -0
  172. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/05-pipelines.md +460 -0
  173. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/06-skills.md +43 -0
  174. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/07-projects.md +73 -0
  175. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/08-rules.md +53 -0
  176. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/09-issue-autofix.md +55 -0
  177. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/10-troubleshooting.md +89 -0
  178. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/11-workspace.md +810 -0
  179. package/.forge/worktrees/pipeline-0a33c50d/lib/help-docs/CLAUDE.md +62 -0
  180. package/.forge/worktrees/pipeline-0a33c50d/lib/init.ts +266 -0
  181. package/.forge/worktrees/pipeline-0a33c50d/lib/issue-scanner.ts +298 -0
  182. package/.forge/worktrees/pipeline-0a33c50d/lib/logger.ts +79 -0
  183. package/.forge/worktrees/pipeline-0a33c50d/lib/notifications.ts +75 -0
  184. package/.forge/worktrees/pipeline-0a33c50d/lib/notify.ts +108 -0
  185. package/.forge/worktrees/pipeline-0a33c50d/lib/password.ts +97 -0
  186. package/.forge/worktrees/pipeline-0a33c50d/lib/pipeline-scheduler.ts +373 -0
  187. package/.forge/worktrees/pipeline-0a33c50d/lib/pipeline.ts +1438 -0
  188. package/.forge/worktrees/pipeline-0a33c50d/lib/plugins/executor.ts +347 -0
  189. package/.forge/worktrees/pipeline-0a33c50d/lib/plugins/registry.ts +228 -0
  190. package/.forge/worktrees/pipeline-0a33c50d/lib/plugins/types.ts +103 -0
  191. package/.forge/worktrees/pipeline-0a33c50d/lib/project-sessions.ts +53 -0
  192. package/.forge/worktrees/pipeline-0a33c50d/lib/projects.ts +86 -0
  193. package/.forge/worktrees/pipeline-0a33c50d/lib/session-manager.ts +156 -0
  194. package/.forge/worktrees/pipeline-0a33c50d/lib/session-utils.ts +53 -0
  195. package/.forge/worktrees/pipeline-0a33c50d/lib/session-watcher.ts +345 -0
  196. package/.forge/worktrees/pipeline-0a33c50d/lib/settings.ts +195 -0
  197. package/.forge/worktrees/pipeline-0a33c50d/lib/skills.ts +458 -0
  198. package/.forge/worktrees/pipeline-0a33c50d/lib/task-manager.ts +949 -0
  199. package/.forge/worktrees/pipeline-0a33c50d/lib/telegram-bot.ts +1477 -0
  200. package/.forge/worktrees/pipeline-0a33c50d/lib/telegram-standalone.ts +83 -0
  201. package/.forge/worktrees/pipeline-0a33c50d/lib/terminal-server.ts +70 -0
  202. package/.forge/worktrees/pipeline-0a33c50d/lib/terminal-standalone.ts +421 -0
  203. package/.forge/worktrees/pipeline-0a33c50d/lib/usage-scanner.ts +249 -0
  204. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/__tests__/state-machine.test.ts +388 -0
  205. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/__tests__/workspace.test.ts +311 -0
  206. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/agent-bus.ts +416 -0
  207. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/agent-worker.ts +655 -0
  208. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/backends/api-backend.ts +262 -0
  209. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/backends/cli-backend.ts +491 -0
  210. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/index.ts +82 -0
  211. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/manager.ts +136 -0
  212. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/orchestrator.ts +3400 -0
  213. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/persistence.ts +309 -0
  214. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/presets.ts +649 -0
  215. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/requests.ts +287 -0
  216. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/session-monitor.ts +240 -0
  217. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/skill-installer.ts +275 -0
  218. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/smith-memory.ts +498 -0
  219. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/types.ts +241 -0
  220. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace/watch-manager.ts +560 -0
  221. package/.forge/worktrees/pipeline-0a33c50d/lib/workspace-standalone.ts +911 -0
  222. package/.forge/worktrees/pipeline-0a33c50d/middleware.ts +51 -0
  223. package/.forge/worktrees/pipeline-0a33c50d/next.config.ts +26 -0
  224. package/.forge/worktrees/pipeline-0a33c50d/package.json +74 -0
  225. package/.forge/worktrees/pipeline-0a33c50d/pnpm-lock.yaml +3719 -0
  226. package/.forge/worktrees/pipeline-0a33c50d/pnpm-workspace.yaml +1 -0
  227. package/.forge/worktrees/pipeline-0a33c50d/postcss.config.mjs +7 -0
  228. package/.forge/worktrees/pipeline-0a33c50d/publish.sh +133 -0
  229. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/README.md +66 -0
  230. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/results/.gitignore +2 -0
  231. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/run.ts +635 -0
  232. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/01-text-utils/task.md +26 -0
  233. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  234. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  235. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/02-pagination/task.md +48 -0
  236. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  237. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  238. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  239. package/.forge/worktrees/pipeline-0a33c50d/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  240. package/.forge/worktrees/pipeline-0a33c50d/scripts/verify-usage.ts +178 -0
  241. package/.forge/worktrees/pipeline-0a33c50d/src/config/index.ts +129 -0
  242. package/.forge/worktrees/pipeline-0a33c50d/src/core/db/database.ts +259 -0
  243. package/.forge/worktrees/pipeline-0a33c50d/src/core/memory/strategy.ts +32 -0
  244. package/.forge/worktrees/pipeline-0a33c50d/src/core/providers/chat.ts +65 -0
  245. package/.forge/worktrees/pipeline-0a33c50d/src/core/providers/registry.ts +60 -0
  246. package/.forge/worktrees/pipeline-0a33c50d/src/core/session/manager.ts +190 -0
  247. package/.forge/worktrees/pipeline-0a33c50d/src/types/index.ts +129 -0
  248. package/.forge/worktrees/pipeline-0a33c50d/start.sh +31 -0
  249. package/.forge/worktrees/pipeline-0a33c50d/templates/smith-lead.json +45 -0
  250. package/.forge/worktrees/pipeline-0a33c50d/tsconfig.json +42 -0
  251. package/.forge/worktrees/pipeline-2ba01c10/CLAUDE.md +86 -0
  252. package/.forge/worktrees/pipeline-2ba01c10/README.md +136 -0
  253. package/.forge/worktrees/pipeline-2ba01c10/RELEASE_NOTES.md +11 -0
  254. package/.forge/worktrees/pipeline-2ba01c10/app/api/agents/route.ts +17 -0
  255. package/.forge/worktrees/pipeline-2ba01c10/app/api/auth/[...nextauth]/route.ts +3 -0
  256. package/.forge/worktrees/pipeline-2ba01c10/app/api/auth/verify/route.ts +46 -0
  257. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude/[id]/route.ts +31 -0
  258. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude/[id]/stream/route.ts +63 -0
  259. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude/route.ts +28 -0
  260. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  261. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  262. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude-sessions/[projectName]/route.ts +37 -0
  263. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude-sessions/sync/route.ts +17 -0
  264. package/.forge/worktrees/pipeline-2ba01c10/app/api/claude-templates/route.ts +145 -0
  265. package/.forge/worktrees/pipeline-2ba01c10/app/api/code/route.ts +299 -0
  266. package/.forge/worktrees/pipeline-2ba01c10/app/api/delivery/[id]/route.ts +62 -0
  267. package/.forge/worktrees/pipeline-2ba01c10/app/api/delivery/route.ts +40 -0
  268. package/.forge/worktrees/pipeline-2ba01c10/app/api/detect-cli/route.ts +46 -0
  269. package/.forge/worktrees/pipeline-2ba01c10/app/api/docs/route.ts +176 -0
  270. package/.forge/worktrees/pipeline-2ba01c10/app/api/docs/sessions/route.ts +54 -0
  271. package/.forge/worktrees/pipeline-2ba01c10/app/api/favorites/route.ts +26 -0
  272. package/.forge/worktrees/pipeline-2ba01c10/app/api/flows/route.ts +6 -0
  273. package/.forge/worktrees/pipeline-2ba01c10/app/api/flows/run/route.ts +19 -0
  274. package/.forge/worktrees/pipeline-2ba01c10/app/api/git/route.ts +149 -0
  275. package/.forge/worktrees/pipeline-2ba01c10/app/api/help/route.ts +84 -0
  276. package/.forge/worktrees/pipeline-2ba01c10/app/api/issue-scanner/route.ts +116 -0
  277. package/.forge/worktrees/pipeline-2ba01c10/app/api/logs/route.ts +100 -0
  278. package/.forge/worktrees/pipeline-2ba01c10/app/api/mobile-chat/route.ts +115 -0
  279. package/.forge/worktrees/pipeline-2ba01c10/app/api/monitor/route.ts +74 -0
  280. package/.forge/worktrees/pipeline-2ba01c10/app/api/notifications/route.ts +42 -0
  281. package/.forge/worktrees/pipeline-2ba01c10/app/api/notify/test/route.ts +33 -0
  282. package/.forge/worktrees/pipeline-2ba01c10/app/api/online/route.ts +40 -0
  283. package/.forge/worktrees/pipeline-2ba01c10/app/api/pipelines/[id]/route.ts +41 -0
  284. package/.forge/worktrees/pipeline-2ba01c10/app/api/pipelines/route.ts +90 -0
  285. package/.forge/worktrees/pipeline-2ba01c10/app/api/plugins/route.ts +75 -0
  286. package/.forge/worktrees/pipeline-2ba01c10/app/api/preview/[...path]/route.ts +64 -0
  287. package/.forge/worktrees/pipeline-2ba01c10/app/api/preview/route.ts +156 -0
  288. package/.forge/worktrees/pipeline-2ba01c10/app/api/project-pipelines/route.ts +91 -0
  289. package/.forge/worktrees/pipeline-2ba01c10/app/api/project-sessions/route.ts +61 -0
  290. package/.forge/worktrees/pipeline-2ba01c10/app/api/projects/route.ts +26 -0
  291. package/.forge/worktrees/pipeline-2ba01c10/app/api/sessions/[id]/chat/route.ts +64 -0
  292. package/.forge/worktrees/pipeline-2ba01c10/app/api/sessions/[id]/messages/route.ts +9 -0
  293. package/.forge/worktrees/pipeline-2ba01c10/app/api/sessions/[id]/route.ts +17 -0
  294. package/.forge/worktrees/pipeline-2ba01c10/app/api/sessions/route.ts +20 -0
  295. package/.forge/worktrees/pipeline-2ba01c10/app/api/settings/route.ts +64 -0
  296. package/.forge/worktrees/pipeline-2ba01c10/app/api/skills/local/route.ts +228 -0
  297. package/.forge/worktrees/pipeline-2ba01c10/app/api/skills/route.ts +182 -0
  298. package/.forge/worktrees/pipeline-2ba01c10/app/api/smith-templates/route.ts +81 -0
  299. package/.forge/worktrees/pipeline-2ba01c10/app/api/status/route.ts +12 -0
  300. package/.forge/worktrees/pipeline-2ba01c10/app/api/tabs/route.ts +25 -0
  301. package/.forge/worktrees/pipeline-2ba01c10/app/api/tasks/[id]/route.ts +51 -0
  302. package/.forge/worktrees/pipeline-2ba01c10/app/api/tasks/[id]/stream/route.ts +77 -0
  303. package/.forge/worktrees/pipeline-2ba01c10/app/api/tasks/link/route.ts +37 -0
  304. package/.forge/worktrees/pipeline-2ba01c10/app/api/tasks/route.ts +44 -0
  305. package/.forge/worktrees/pipeline-2ba01c10/app/api/tasks/session/route.ts +14 -0
  306. package/.forge/worktrees/pipeline-2ba01c10/app/api/telegram/route.ts +23 -0
  307. package/.forge/worktrees/pipeline-2ba01c10/app/api/templates/route.ts +6 -0
  308. package/.forge/worktrees/pipeline-2ba01c10/app/api/terminal-bell/route.ts +35 -0
  309. package/.forge/worktrees/pipeline-2ba01c10/app/api/terminal-cwd/route.ts +19 -0
  310. package/.forge/worktrees/pipeline-2ba01c10/app/api/terminal-state/route.ts +15 -0
  311. package/.forge/worktrees/pipeline-2ba01c10/app/api/tunnel/route.ts +26 -0
  312. package/.forge/worktrees/pipeline-2ba01c10/app/api/upgrade/route.ts +43 -0
  313. package/.forge/worktrees/pipeline-2ba01c10/app/api/usage/route.ts +20 -0
  314. package/.forge/worktrees/pipeline-2ba01c10/app/api/version/route.ts +78 -0
  315. package/.forge/worktrees/pipeline-2ba01c10/app/api/watchers/route.ts +33 -0
  316. package/.forge/worktrees/pipeline-2ba01c10/app/api/workspace/[id]/agents/route.ts +35 -0
  317. package/.forge/worktrees/pipeline-2ba01c10/app/api/workspace/[id]/memory/route.ts +23 -0
  318. package/.forge/worktrees/pipeline-2ba01c10/app/api/workspace/[id]/smith/route.ts +22 -0
  319. package/.forge/worktrees/pipeline-2ba01c10/app/api/workspace/[id]/stream/route.ts +28 -0
  320. package/.forge/worktrees/pipeline-2ba01c10/app/api/workspace/route.ts +100 -0
  321. package/.forge/worktrees/pipeline-2ba01c10/app/global-error.tsx +21 -0
  322. package/.forge/worktrees/pipeline-2ba01c10/app/globals.css +52 -0
  323. package/.forge/worktrees/pipeline-2ba01c10/app/icon.ico +0 -0
  324. package/.forge/worktrees/pipeline-2ba01c10/app/icon.png +0 -0
  325. package/.forge/worktrees/pipeline-2ba01c10/app/icon.svg +106 -0
  326. package/.forge/worktrees/pipeline-2ba01c10/app/layout.tsx +17 -0
  327. package/.forge/worktrees/pipeline-2ba01c10/app/login/LoginForm.tsx +96 -0
  328. package/.forge/worktrees/pipeline-2ba01c10/app/login/page.tsx +10 -0
  329. package/.forge/worktrees/pipeline-2ba01c10/app/mobile/page.tsx +9 -0
  330. package/.forge/worktrees/pipeline-2ba01c10/app/page.tsx +21 -0
  331. package/.forge/worktrees/pipeline-2ba01c10/bin/forge-server.mjs +484 -0
  332. package/.forge/worktrees/pipeline-2ba01c10/check-forge-status.sh +71 -0
  333. package/.forge/worktrees/pipeline-2ba01c10/cli/mw.ts +579 -0
  334. package/.forge/worktrees/pipeline-2ba01c10/components/BrowserPanel.tsx +175 -0
  335. package/.forge/worktrees/pipeline-2ba01c10/components/ChatPanel.tsx +191 -0
  336. package/.forge/worktrees/pipeline-2ba01c10/components/ClaudeTerminal.tsx +267 -0
  337. package/.forge/worktrees/pipeline-2ba01c10/components/CodeViewer.tsx +787 -0
  338. package/.forge/worktrees/pipeline-2ba01c10/components/ConversationEditor.tsx +411 -0
  339. package/.forge/worktrees/pipeline-2ba01c10/components/ConversationGraphView.tsx +347 -0
  340. package/.forge/worktrees/pipeline-2ba01c10/components/ConversationTerminalView.tsx +303 -0
  341. package/.forge/worktrees/pipeline-2ba01c10/components/Dashboard.tsx +807 -0
  342. package/.forge/worktrees/pipeline-2ba01c10/components/DashboardWrapper.tsx +9 -0
  343. package/.forge/worktrees/pipeline-2ba01c10/components/DeliveryFlowEditor.tsx +491 -0
  344. package/.forge/worktrees/pipeline-2ba01c10/components/DeliveryList.tsx +230 -0
  345. package/.forge/worktrees/pipeline-2ba01c10/components/DeliveryWorkspace.tsx +589 -0
  346. package/.forge/worktrees/pipeline-2ba01c10/components/DocTerminal.tsx +187 -0
  347. package/.forge/worktrees/pipeline-2ba01c10/components/DocsViewer.tsx +574 -0
  348. package/.forge/worktrees/pipeline-2ba01c10/components/HelpDialog.tsx +169 -0
  349. package/.forge/worktrees/pipeline-2ba01c10/components/HelpTerminal.tsx +141 -0
  350. package/.forge/worktrees/pipeline-2ba01c10/components/InlinePipelineView.tsx +111 -0
  351. package/.forge/worktrees/pipeline-2ba01c10/components/LogViewer.tsx +194 -0
  352. package/.forge/worktrees/pipeline-2ba01c10/components/MarkdownContent.tsx +73 -0
  353. package/.forge/worktrees/pipeline-2ba01c10/components/MobileView.tsx +385 -0
  354. package/.forge/worktrees/pipeline-2ba01c10/components/MonitorPanel.tsx +122 -0
  355. package/.forge/worktrees/pipeline-2ba01c10/components/NewSessionModal.tsx +93 -0
  356. package/.forge/worktrees/pipeline-2ba01c10/components/NewTaskModal.tsx +492 -0
  357. package/.forge/worktrees/pipeline-2ba01c10/components/PipelineEditor.tsx +570 -0
  358. package/.forge/worktrees/pipeline-2ba01c10/components/PipelineView.tsx +1018 -0
  359. package/.forge/worktrees/pipeline-2ba01c10/components/PluginsPanel.tsx +472 -0
  360. package/.forge/worktrees/pipeline-2ba01c10/components/ProjectDetail.tsx +1618 -0
  361. package/.forge/worktrees/pipeline-2ba01c10/components/ProjectList.tsx +108 -0
  362. package/.forge/worktrees/pipeline-2ba01c10/components/ProjectManager.tsx +401 -0
  363. package/.forge/worktrees/pipeline-2ba01c10/components/SessionList.tsx +74 -0
  364. package/.forge/worktrees/pipeline-2ba01c10/components/SessionView.tsx +726 -0
  365. package/.forge/worktrees/pipeline-2ba01c10/components/SettingsModal.tsx +1647 -0
  366. package/.forge/worktrees/pipeline-2ba01c10/components/SkillsPanel.tsx +969 -0
  367. package/.forge/worktrees/pipeline-2ba01c10/components/StatusBar.tsx +99 -0
  368. package/.forge/worktrees/pipeline-2ba01c10/components/TabBar.tsx +46 -0
  369. package/.forge/worktrees/pipeline-2ba01c10/components/TaskBoard.tsx +113 -0
  370. package/.forge/worktrees/pipeline-2ba01c10/components/TaskDetail.tsx +372 -0
  371. package/.forge/worktrees/pipeline-2ba01c10/components/TerminalLauncher.tsx +398 -0
  372. package/.forge/worktrees/pipeline-2ba01c10/components/TunnelToggle.tsx +206 -0
  373. package/.forge/worktrees/pipeline-2ba01c10/components/UsagePanel.tsx +207 -0
  374. package/.forge/worktrees/pipeline-2ba01c10/components/WebTerminal.tsx +1683 -0
  375. package/.forge/worktrees/pipeline-2ba01c10/components/WorkspaceTree.tsx +221 -0
  376. package/.forge/worktrees/pipeline-2ba01c10/components/WorkspaceView.tsx +4048 -0
  377. package/.forge/worktrees/pipeline-2ba01c10/dev-test.sh +5 -0
  378. package/.forge/worktrees/pipeline-2ba01c10/docs/Forge_Memory_Layer_Design.docx +0 -0
  379. package/.forge/worktrees/pipeline-2ba01c10/docs/Forge_Strategy_Research_2026.docx +0 -0
  380. package/.forge/worktrees/pipeline-2ba01c10/docs/LOCAL-DEPLOY.md +144 -0
  381. package/.forge/worktrees/pipeline-2ba01c10/docs/roadmap-multi-agent-workflow.md +330 -0
  382. package/.forge/worktrees/pipeline-2ba01c10/forge-logo.png +0 -0
  383. package/.forge/worktrees/pipeline-2ba01c10/forge-logo.svg +106 -0
  384. package/.forge/worktrees/pipeline-2ba01c10/hooks/useSidebarResize.ts +52 -0
  385. package/.forge/worktrees/pipeline-2ba01c10/install.sh +29 -0
  386. package/.forge/worktrees/pipeline-2ba01c10/instrumentation.ts +35 -0
  387. package/.forge/worktrees/pipeline-2ba01c10/lib/agents/claude-adapter.ts +104 -0
  388. package/.forge/worktrees/pipeline-2ba01c10/lib/agents/generic-adapter.ts +64 -0
  389. package/.forge/worktrees/pipeline-2ba01c10/lib/agents/index.ts +245 -0
  390. package/.forge/worktrees/pipeline-2ba01c10/lib/agents/types.ts +70 -0
  391. package/.forge/worktrees/pipeline-2ba01c10/lib/artifacts.ts +106 -0
  392. package/.forge/worktrees/pipeline-2ba01c10/lib/auth.ts +62 -0
  393. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/docker.yaml +70 -0
  394. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/http.yaml +66 -0
  395. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/jenkins.yaml +92 -0
  396. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/llm-vision.yaml +85 -0
  397. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/playwright.yaml +111 -0
  398. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/shell-command.yaml +60 -0
  399. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/slack.yaml +48 -0
  400. package/.forge/worktrees/pipeline-2ba01c10/lib/builtin-plugins/webhook.yaml +56 -0
  401. package/.forge/worktrees/pipeline-2ba01c10/lib/claude-process.ts +352 -0
  402. package/.forge/worktrees/pipeline-2ba01c10/lib/claude-sessions.ts +266 -0
  403. package/.forge/worktrees/pipeline-2ba01c10/lib/claude-templates.ts +227 -0
  404. package/.forge/worktrees/pipeline-2ba01c10/lib/cloudflared.ts +424 -0
  405. package/.forge/worktrees/pipeline-2ba01c10/lib/crypto.ts +67 -0
  406. package/.forge/worktrees/pipeline-2ba01c10/lib/delivery.ts +787 -0
  407. package/.forge/worktrees/pipeline-2ba01c10/lib/dirs.ts +99 -0
  408. package/.forge/worktrees/pipeline-2ba01c10/lib/flows.ts +86 -0
  409. package/.forge/worktrees/pipeline-2ba01c10/lib/forge-mcp-server.ts +717 -0
  410. package/.forge/worktrees/pipeline-2ba01c10/lib/forge-skills/forge-inbox.md +38 -0
  411. package/.forge/worktrees/pipeline-2ba01c10/lib/forge-skills/forge-send.md +47 -0
  412. package/.forge/worktrees/pipeline-2ba01c10/lib/forge-skills/forge-status.md +32 -0
  413. package/.forge/worktrees/pipeline-2ba01c10/lib/forge-skills/forge-workspace-sync.md +37 -0
  414. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/00-overview.md +40 -0
  415. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/01-settings.md +194 -0
  416. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/02-telegram.md +41 -0
  417. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/03-tunnel.md +31 -0
  418. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/04-tasks.md +52 -0
  419. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/05-pipelines.md +460 -0
  420. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/06-skills.md +43 -0
  421. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/07-projects.md +73 -0
  422. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/08-rules.md +53 -0
  423. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/09-issue-autofix.md +55 -0
  424. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/10-troubleshooting.md +89 -0
  425. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/11-workspace.md +810 -0
  426. package/.forge/worktrees/pipeline-2ba01c10/lib/help-docs/CLAUDE.md +62 -0
  427. package/.forge/worktrees/pipeline-2ba01c10/lib/init.ts +266 -0
  428. package/.forge/worktrees/pipeline-2ba01c10/lib/issue-scanner.ts +298 -0
  429. package/.forge/worktrees/pipeline-2ba01c10/lib/logger.ts +79 -0
  430. package/.forge/worktrees/pipeline-2ba01c10/lib/notifications.ts +75 -0
  431. package/.forge/worktrees/pipeline-2ba01c10/lib/notify.ts +108 -0
  432. package/.forge/worktrees/pipeline-2ba01c10/lib/password.ts +97 -0
  433. package/.forge/worktrees/pipeline-2ba01c10/lib/pipeline-scheduler.ts +373 -0
  434. package/.forge/worktrees/pipeline-2ba01c10/lib/pipeline.ts +1438 -0
  435. package/.forge/worktrees/pipeline-2ba01c10/lib/plugins/executor.ts +347 -0
  436. package/.forge/worktrees/pipeline-2ba01c10/lib/plugins/registry.ts +228 -0
  437. package/.forge/worktrees/pipeline-2ba01c10/lib/plugins/types.ts +103 -0
  438. package/.forge/worktrees/pipeline-2ba01c10/lib/project-sessions.ts +53 -0
  439. package/.forge/worktrees/pipeline-2ba01c10/lib/projects.ts +86 -0
  440. package/.forge/worktrees/pipeline-2ba01c10/lib/session-manager.ts +156 -0
  441. package/.forge/worktrees/pipeline-2ba01c10/lib/session-utils.ts +53 -0
  442. package/.forge/worktrees/pipeline-2ba01c10/lib/session-watcher.ts +345 -0
  443. package/.forge/worktrees/pipeline-2ba01c10/lib/settings.ts +195 -0
  444. package/.forge/worktrees/pipeline-2ba01c10/lib/skills.ts +458 -0
  445. package/.forge/worktrees/pipeline-2ba01c10/lib/task-manager.ts +949 -0
  446. package/.forge/worktrees/pipeline-2ba01c10/lib/telegram-bot.ts +1477 -0
  447. package/.forge/worktrees/pipeline-2ba01c10/lib/telegram-standalone.ts +83 -0
  448. package/.forge/worktrees/pipeline-2ba01c10/lib/terminal-server.ts +70 -0
  449. package/.forge/worktrees/pipeline-2ba01c10/lib/terminal-standalone.ts +421 -0
  450. package/.forge/worktrees/pipeline-2ba01c10/lib/usage-scanner.ts +249 -0
  451. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/__tests__/state-machine.test.ts +388 -0
  452. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/__tests__/workspace.test.ts +311 -0
  453. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/agent-bus.ts +416 -0
  454. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/agent-worker.ts +655 -0
  455. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/backends/api-backend.ts +262 -0
  456. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/backends/cli-backend.ts +491 -0
  457. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/index.ts +82 -0
  458. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/manager.ts +136 -0
  459. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/orchestrator.ts +3400 -0
  460. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/persistence.ts +309 -0
  461. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/presets.ts +649 -0
  462. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/requests.ts +287 -0
  463. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/session-monitor.ts +240 -0
  464. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/skill-installer.ts +275 -0
  465. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/smith-memory.ts +498 -0
  466. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/types.ts +241 -0
  467. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace/watch-manager.ts +560 -0
  468. package/.forge/worktrees/pipeline-2ba01c10/lib/workspace-standalone.ts +911 -0
  469. package/.forge/worktrees/pipeline-2ba01c10/middleware.ts +51 -0
  470. package/.forge/worktrees/pipeline-2ba01c10/next.config.ts +26 -0
  471. package/.forge/worktrees/pipeline-2ba01c10/package.json +74 -0
  472. package/.forge/worktrees/pipeline-2ba01c10/pnpm-lock.yaml +3719 -0
  473. package/.forge/worktrees/pipeline-2ba01c10/pnpm-workspace.yaml +1 -0
  474. package/.forge/worktrees/pipeline-2ba01c10/postcss.config.mjs +7 -0
  475. package/.forge/worktrees/pipeline-2ba01c10/publish.sh +133 -0
  476. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/README.md +66 -0
  477. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/results/.gitignore +2 -0
  478. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/run.ts +635 -0
  479. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/01-text-utils/task.md +26 -0
  480. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  481. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  482. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/02-pagination/task.md +48 -0
  483. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  484. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  485. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  486. package/.forge/worktrees/pipeline-2ba01c10/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  487. package/.forge/worktrees/pipeline-2ba01c10/scripts/verify-usage.ts +178 -0
  488. package/.forge/worktrees/pipeline-2ba01c10/src/config/index.ts +129 -0
  489. package/.forge/worktrees/pipeline-2ba01c10/src/core/db/database.ts +259 -0
  490. package/.forge/worktrees/pipeline-2ba01c10/src/core/memory/strategy.ts +32 -0
  491. package/.forge/worktrees/pipeline-2ba01c10/src/core/providers/chat.ts +65 -0
  492. package/.forge/worktrees/pipeline-2ba01c10/src/core/providers/registry.ts +60 -0
  493. package/.forge/worktrees/pipeline-2ba01c10/src/core/session/manager.ts +190 -0
  494. package/.forge/worktrees/pipeline-2ba01c10/src/types/index.ts +129 -0
  495. package/.forge/worktrees/pipeline-2ba01c10/start.sh +31 -0
  496. package/.forge/worktrees/pipeline-2ba01c10/templates/smith-lead.json +45 -0
  497. package/.forge/worktrees/pipeline-2ba01c10/tsconfig.json +42 -0
  498. package/.forge/worktrees/pipeline-3156a8b3/CLAUDE.md +86 -0
  499. package/.forge/worktrees/pipeline-3156a8b3/README.md +136 -0
  500. package/.forge/worktrees/pipeline-3156a8b3/RELEASE_NOTES.md +11 -0
  501. package/.forge/worktrees/pipeline-3156a8b3/app/api/agents/route.ts +17 -0
  502. package/.forge/worktrees/pipeline-3156a8b3/app/api/auth/[...nextauth]/route.ts +3 -0
  503. package/.forge/worktrees/pipeline-3156a8b3/app/api/auth/verify/route.ts +46 -0
  504. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude/[id]/route.ts +31 -0
  505. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude/[id]/stream/route.ts +63 -0
  506. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude/route.ts +28 -0
  507. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  508. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  509. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude-sessions/[projectName]/route.ts +37 -0
  510. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude-sessions/sync/route.ts +17 -0
  511. package/.forge/worktrees/pipeline-3156a8b3/app/api/claude-templates/route.ts +145 -0
  512. package/.forge/worktrees/pipeline-3156a8b3/app/api/code/route.ts +299 -0
  513. package/.forge/worktrees/pipeline-3156a8b3/app/api/delivery/[id]/route.ts +62 -0
  514. package/.forge/worktrees/pipeline-3156a8b3/app/api/delivery/route.ts +40 -0
  515. package/.forge/worktrees/pipeline-3156a8b3/app/api/detect-cli/route.ts +46 -0
  516. package/.forge/worktrees/pipeline-3156a8b3/app/api/docs/route.ts +176 -0
  517. package/.forge/worktrees/pipeline-3156a8b3/app/api/docs/sessions/route.ts +54 -0
  518. package/.forge/worktrees/pipeline-3156a8b3/app/api/favorites/route.ts +26 -0
  519. package/.forge/worktrees/pipeline-3156a8b3/app/api/flows/route.ts +6 -0
  520. package/.forge/worktrees/pipeline-3156a8b3/app/api/flows/run/route.ts +19 -0
  521. package/.forge/worktrees/pipeline-3156a8b3/app/api/git/route.ts +149 -0
  522. package/.forge/worktrees/pipeline-3156a8b3/app/api/help/route.ts +84 -0
  523. package/.forge/worktrees/pipeline-3156a8b3/app/api/issue-scanner/route.ts +116 -0
  524. package/.forge/worktrees/pipeline-3156a8b3/app/api/logs/route.ts +100 -0
  525. package/.forge/worktrees/pipeline-3156a8b3/app/api/mobile-chat/route.ts +115 -0
  526. package/.forge/worktrees/pipeline-3156a8b3/app/api/monitor/route.ts +74 -0
  527. package/.forge/worktrees/pipeline-3156a8b3/app/api/notifications/route.ts +42 -0
  528. package/.forge/worktrees/pipeline-3156a8b3/app/api/notify/test/route.ts +33 -0
  529. package/.forge/worktrees/pipeline-3156a8b3/app/api/online/route.ts +40 -0
  530. package/.forge/worktrees/pipeline-3156a8b3/app/api/pipelines/[id]/route.ts +41 -0
  531. package/.forge/worktrees/pipeline-3156a8b3/app/api/pipelines/route.ts +90 -0
  532. package/.forge/worktrees/pipeline-3156a8b3/app/api/plugins/route.ts +75 -0
  533. package/.forge/worktrees/pipeline-3156a8b3/app/api/preview/[...path]/route.ts +64 -0
  534. package/.forge/worktrees/pipeline-3156a8b3/app/api/preview/route.ts +156 -0
  535. package/.forge/worktrees/pipeline-3156a8b3/app/api/project-pipelines/route.ts +91 -0
  536. package/.forge/worktrees/pipeline-3156a8b3/app/api/project-sessions/route.ts +61 -0
  537. package/.forge/worktrees/pipeline-3156a8b3/app/api/projects/route.ts +26 -0
  538. package/.forge/worktrees/pipeline-3156a8b3/app/api/sessions/[id]/chat/route.ts +64 -0
  539. package/.forge/worktrees/pipeline-3156a8b3/app/api/sessions/[id]/messages/route.ts +9 -0
  540. package/.forge/worktrees/pipeline-3156a8b3/app/api/sessions/[id]/route.ts +17 -0
  541. package/.forge/worktrees/pipeline-3156a8b3/app/api/sessions/route.ts +20 -0
  542. package/.forge/worktrees/pipeline-3156a8b3/app/api/settings/route.ts +64 -0
  543. package/.forge/worktrees/pipeline-3156a8b3/app/api/skills/local/route.ts +228 -0
  544. package/.forge/worktrees/pipeline-3156a8b3/app/api/skills/route.ts +182 -0
  545. package/.forge/worktrees/pipeline-3156a8b3/app/api/smith-templates/route.ts +81 -0
  546. package/.forge/worktrees/pipeline-3156a8b3/app/api/status/route.ts +12 -0
  547. package/.forge/worktrees/pipeline-3156a8b3/app/api/tabs/route.ts +25 -0
  548. package/.forge/worktrees/pipeline-3156a8b3/app/api/tasks/[id]/route.ts +51 -0
  549. package/.forge/worktrees/pipeline-3156a8b3/app/api/tasks/[id]/stream/route.ts +77 -0
  550. package/.forge/worktrees/pipeline-3156a8b3/app/api/tasks/link/route.ts +37 -0
  551. package/.forge/worktrees/pipeline-3156a8b3/app/api/tasks/route.ts +44 -0
  552. package/.forge/worktrees/pipeline-3156a8b3/app/api/tasks/session/route.ts +14 -0
  553. package/.forge/worktrees/pipeline-3156a8b3/app/api/telegram/route.ts +23 -0
  554. package/.forge/worktrees/pipeline-3156a8b3/app/api/templates/route.ts +6 -0
  555. package/.forge/worktrees/pipeline-3156a8b3/app/api/terminal-bell/route.ts +35 -0
  556. package/.forge/worktrees/pipeline-3156a8b3/app/api/terminal-cwd/route.ts +19 -0
  557. package/.forge/worktrees/pipeline-3156a8b3/app/api/terminal-state/route.ts +15 -0
  558. package/.forge/worktrees/pipeline-3156a8b3/app/api/tunnel/route.ts +26 -0
  559. package/.forge/worktrees/pipeline-3156a8b3/app/api/upgrade/route.ts +43 -0
  560. package/.forge/worktrees/pipeline-3156a8b3/app/api/usage/route.ts +20 -0
  561. package/.forge/worktrees/pipeline-3156a8b3/app/api/version/route.ts +78 -0
  562. package/.forge/worktrees/pipeline-3156a8b3/app/api/watchers/route.ts +33 -0
  563. package/.forge/worktrees/pipeline-3156a8b3/app/api/workspace/[id]/agents/route.ts +35 -0
  564. package/.forge/worktrees/pipeline-3156a8b3/app/api/workspace/[id]/memory/route.ts +23 -0
  565. package/.forge/worktrees/pipeline-3156a8b3/app/api/workspace/[id]/smith/route.ts +22 -0
  566. package/.forge/worktrees/pipeline-3156a8b3/app/api/workspace/[id]/stream/route.ts +28 -0
  567. package/.forge/worktrees/pipeline-3156a8b3/app/api/workspace/route.ts +100 -0
  568. package/.forge/worktrees/pipeline-3156a8b3/app/global-error.tsx +21 -0
  569. package/.forge/worktrees/pipeline-3156a8b3/app/globals.css +52 -0
  570. package/.forge/worktrees/pipeline-3156a8b3/app/icon.ico +0 -0
  571. package/.forge/worktrees/pipeline-3156a8b3/app/icon.png +0 -0
  572. package/.forge/worktrees/pipeline-3156a8b3/app/icon.svg +106 -0
  573. package/.forge/worktrees/pipeline-3156a8b3/app/layout.tsx +17 -0
  574. package/.forge/worktrees/pipeline-3156a8b3/app/login/LoginForm.tsx +96 -0
  575. package/.forge/worktrees/pipeline-3156a8b3/app/login/page.tsx +10 -0
  576. package/.forge/worktrees/pipeline-3156a8b3/app/mobile/page.tsx +9 -0
  577. package/.forge/worktrees/pipeline-3156a8b3/app/page.tsx +21 -0
  578. package/.forge/worktrees/pipeline-3156a8b3/bin/forge-server.mjs +484 -0
  579. package/.forge/worktrees/pipeline-3156a8b3/check-forge-status.sh +71 -0
  580. package/.forge/worktrees/pipeline-3156a8b3/cli/mw.ts +579 -0
  581. package/.forge/worktrees/pipeline-3156a8b3/components/BrowserPanel.tsx +175 -0
  582. package/.forge/worktrees/pipeline-3156a8b3/components/ChatPanel.tsx +191 -0
  583. package/.forge/worktrees/pipeline-3156a8b3/components/ClaudeTerminal.tsx +267 -0
  584. package/.forge/worktrees/pipeline-3156a8b3/components/CodeViewer.tsx +787 -0
  585. package/.forge/worktrees/pipeline-3156a8b3/components/ConversationEditor.tsx +411 -0
  586. package/.forge/worktrees/pipeline-3156a8b3/components/ConversationGraphView.tsx +347 -0
  587. package/.forge/worktrees/pipeline-3156a8b3/components/ConversationTerminalView.tsx +303 -0
  588. package/.forge/worktrees/pipeline-3156a8b3/components/Dashboard.tsx +807 -0
  589. package/.forge/worktrees/pipeline-3156a8b3/components/DashboardWrapper.tsx +9 -0
  590. package/.forge/worktrees/pipeline-3156a8b3/components/DeliveryFlowEditor.tsx +491 -0
  591. package/.forge/worktrees/pipeline-3156a8b3/components/DeliveryList.tsx +230 -0
  592. package/.forge/worktrees/pipeline-3156a8b3/components/DeliveryWorkspace.tsx +589 -0
  593. package/.forge/worktrees/pipeline-3156a8b3/components/DocTerminal.tsx +187 -0
  594. package/.forge/worktrees/pipeline-3156a8b3/components/DocsViewer.tsx +574 -0
  595. package/.forge/worktrees/pipeline-3156a8b3/components/HelpDialog.tsx +169 -0
  596. package/.forge/worktrees/pipeline-3156a8b3/components/HelpTerminal.tsx +141 -0
  597. package/.forge/worktrees/pipeline-3156a8b3/components/InlinePipelineView.tsx +111 -0
  598. package/.forge/worktrees/pipeline-3156a8b3/components/LogViewer.tsx +194 -0
  599. package/.forge/worktrees/pipeline-3156a8b3/components/MarkdownContent.tsx +73 -0
  600. package/.forge/worktrees/pipeline-3156a8b3/components/MobileView.tsx +385 -0
  601. package/.forge/worktrees/pipeline-3156a8b3/components/MonitorPanel.tsx +122 -0
  602. package/.forge/worktrees/pipeline-3156a8b3/components/NewSessionModal.tsx +93 -0
  603. package/.forge/worktrees/pipeline-3156a8b3/components/NewTaskModal.tsx +492 -0
  604. package/.forge/worktrees/pipeline-3156a8b3/components/PipelineEditor.tsx +570 -0
  605. package/.forge/worktrees/pipeline-3156a8b3/components/PipelineView.tsx +1018 -0
  606. package/.forge/worktrees/pipeline-3156a8b3/components/PluginsPanel.tsx +472 -0
  607. package/.forge/worktrees/pipeline-3156a8b3/components/ProjectDetail.tsx +1618 -0
  608. package/.forge/worktrees/pipeline-3156a8b3/components/ProjectList.tsx +108 -0
  609. package/.forge/worktrees/pipeline-3156a8b3/components/ProjectManager.tsx +401 -0
  610. package/.forge/worktrees/pipeline-3156a8b3/components/SessionList.tsx +74 -0
  611. package/.forge/worktrees/pipeline-3156a8b3/components/SessionView.tsx +726 -0
  612. package/.forge/worktrees/pipeline-3156a8b3/components/SettingsModal.tsx +1647 -0
  613. package/.forge/worktrees/pipeline-3156a8b3/components/SkillsPanel.tsx +969 -0
  614. package/.forge/worktrees/pipeline-3156a8b3/components/StatusBar.tsx +99 -0
  615. package/.forge/worktrees/pipeline-3156a8b3/components/TabBar.tsx +46 -0
  616. package/.forge/worktrees/pipeline-3156a8b3/components/TaskBoard.tsx +113 -0
  617. package/.forge/worktrees/pipeline-3156a8b3/components/TaskDetail.tsx +372 -0
  618. package/.forge/worktrees/pipeline-3156a8b3/components/TerminalLauncher.tsx +398 -0
  619. package/.forge/worktrees/pipeline-3156a8b3/components/TunnelToggle.tsx +206 -0
  620. package/.forge/worktrees/pipeline-3156a8b3/components/UsagePanel.tsx +207 -0
  621. package/.forge/worktrees/pipeline-3156a8b3/components/WebTerminal.tsx +1683 -0
  622. package/.forge/worktrees/pipeline-3156a8b3/components/WorkspaceTree.tsx +221 -0
  623. package/.forge/worktrees/pipeline-3156a8b3/components/WorkspaceView.tsx +4048 -0
  624. package/.forge/worktrees/pipeline-3156a8b3/dev-test.sh +5 -0
  625. package/.forge/worktrees/pipeline-3156a8b3/docs/Forge_Memory_Layer_Design.docx +0 -0
  626. package/.forge/worktrees/pipeline-3156a8b3/docs/Forge_Strategy_Research_2026.docx +0 -0
  627. package/.forge/worktrees/pipeline-3156a8b3/docs/LOCAL-DEPLOY.md +144 -0
  628. package/.forge/worktrees/pipeline-3156a8b3/docs/roadmap-multi-agent-workflow.md +330 -0
  629. package/.forge/worktrees/pipeline-3156a8b3/forge-logo.png +0 -0
  630. package/.forge/worktrees/pipeline-3156a8b3/forge-logo.svg +106 -0
  631. package/.forge/worktrees/pipeline-3156a8b3/hooks/useSidebarResize.ts +52 -0
  632. package/.forge/worktrees/pipeline-3156a8b3/install.sh +29 -0
  633. package/.forge/worktrees/pipeline-3156a8b3/instrumentation.ts +35 -0
  634. package/.forge/worktrees/pipeline-3156a8b3/lib/agents/claude-adapter.ts +104 -0
  635. package/.forge/worktrees/pipeline-3156a8b3/lib/agents/generic-adapter.ts +64 -0
  636. package/.forge/worktrees/pipeline-3156a8b3/lib/agents/index.ts +245 -0
  637. package/.forge/worktrees/pipeline-3156a8b3/lib/agents/types.ts +70 -0
  638. package/.forge/worktrees/pipeline-3156a8b3/lib/artifacts.ts +106 -0
  639. package/.forge/worktrees/pipeline-3156a8b3/lib/auth.ts +62 -0
  640. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/docker.yaml +70 -0
  641. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/http.yaml +66 -0
  642. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/jenkins.yaml +92 -0
  643. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/llm-vision.yaml +85 -0
  644. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/playwright.yaml +111 -0
  645. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/shell-command.yaml +60 -0
  646. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/slack.yaml +48 -0
  647. package/.forge/worktrees/pipeline-3156a8b3/lib/builtin-plugins/webhook.yaml +56 -0
  648. package/.forge/worktrees/pipeline-3156a8b3/lib/claude-process.ts +351 -0
  649. package/.forge/worktrees/pipeline-3156a8b3/lib/claude-sessions.ts +266 -0
  650. package/.forge/worktrees/pipeline-3156a8b3/lib/claude-templates.ts +227 -0
  651. package/.forge/worktrees/pipeline-3156a8b3/lib/cloudflared.ts +424 -0
  652. package/.forge/worktrees/pipeline-3156a8b3/lib/crypto.ts +67 -0
  653. package/.forge/worktrees/pipeline-3156a8b3/lib/delivery.ts +787 -0
  654. package/.forge/worktrees/pipeline-3156a8b3/lib/dirs.ts +99 -0
  655. package/.forge/worktrees/pipeline-3156a8b3/lib/flows.ts +86 -0
  656. package/.forge/worktrees/pipeline-3156a8b3/lib/forge-mcp-server.ts +717 -0
  657. package/.forge/worktrees/pipeline-3156a8b3/lib/forge-skills/forge-inbox.md +38 -0
  658. package/.forge/worktrees/pipeline-3156a8b3/lib/forge-skills/forge-send.md +47 -0
  659. package/.forge/worktrees/pipeline-3156a8b3/lib/forge-skills/forge-status.md +32 -0
  660. package/.forge/worktrees/pipeline-3156a8b3/lib/forge-skills/forge-workspace-sync.md +37 -0
  661. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/00-overview.md +40 -0
  662. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/01-settings.md +194 -0
  663. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/02-telegram.md +41 -0
  664. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/03-tunnel.md +31 -0
  665. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/04-tasks.md +52 -0
  666. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/05-pipelines.md +460 -0
  667. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/06-skills.md +43 -0
  668. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/07-projects.md +73 -0
  669. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/08-rules.md +53 -0
  670. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/09-issue-autofix.md +55 -0
  671. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/10-troubleshooting.md +89 -0
  672. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/11-workspace.md +810 -0
  673. package/.forge/worktrees/pipeline-3156a8b3/lib/help-docs/CLAUDE.md +62 -0
  674. package/.forge/worktrees/pipeline-3156a8b3/lib/init.ts +266 -0
  675. package/.forge/worktrees/pipeline-3156a8b3/lib/issue-scanner.ts +298 -0
  676. package/.forge/worktrees/pipeline-3156a8b3/lib/logger.ts +79 -0
  677. package/.forge/worktrees/pipeline-3156a8b3/lib/notifications.ts +75 -0
  678. package/.forge/worktrees/pipeline-3156a8b3/lib/notify.ts +108 -0
  679. package/.forge/worktrees/pipeline-3156a8b3/lib/password.ts +97 -0
  680. package/.forge/worktrees/pipeline-3156a8b3/lib/pipeline-scheduler.ts +373 -0
  681. package/.forge/worktrees/pipeline-3156a8b3/lib/pipeline.ts +1441 -0
  682. package/.forge/worktrees/pipeline-3156a8b3/lib/plugins/executor.ts +347 -0
  683. package/.forge/worktrees/pipeline-3156a8b3/lib/plugins/registry.ts +228 -0
  684. package/.forge/worktrees/pipeline-3156a8b3/lib/plugins/types.ts +103 -0
  685. package/.forge/worktrees/pipeline-3156a8b3/lib/project-sessions.ts +53 -0
  686. package/.forge/worktrees/pipeline-3156a8b3/lib/projects.ts +86 -0
  687. package/.forge/worktrees/pipeline-3156a8b3/lib/session-manager.ts +156 -0
  688. package/.forge/worktrees/pipeline-3156a8b3/lib/session-utils.ts +53 -0
  689. package/.forge/worktrees/pipeline-3156a8b3/lib/session-watcher.ts +345 -0
  690. package/.forge/worktrees/pipeline-3156a8b3/lib/settings.ts +195 -0
  691. package/.forge/worktrees/pipeline-3156a8b3/lib/skills.ts +458 -0
  692. package/.forge/worktrees/pipeline-3156a8b3/lib/task-manager.ts +949 -0
  693. package/.forge/worktrees/pipeline-3156a8b3/lib/telegram-bot.ts +1477 -0
  694. package/.forge/worktrees/pipeline-3156a8b3/lib/telegram-standalone.ts +83 -0
  695. package/.forge/worktrees/pipeline-3156a8b3/lib/terminal-server.ts +70 -0
  696. package/.forge/worktrees/pipeline-3156a8b3/lib/terminal-standalone.ts +421 -0
  697. package/.forge/worktrees/pipeline-3156a8b3/lib/usage-scanner.ts +249 -0
  698. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/__tests__/state-machine.test.ts +388 -0
  699. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/__tests__/workspace.test.ts +311 -0
  700. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/agent-bus.ts +416 -0
  701. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/agent-worker.ts +655 -0
  702. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/backends/api-backend.ts +262 -0
  703. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/backends/cli-backend.ts +491 -0
  704. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/index.ts +82 -0
  705. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/manager.ts +136 -0
  706. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/orchestrator.ts +3400 -0
  707. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/persistence.ts +309 -0
  708. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/presets.ts +649 -0
  709. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/requests.ts +287 -0
  710. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/session-monitor.ts +240 -0
  711. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/skill-installer.ts +275 -0
  712. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/smith-memory.ts +498 -0
  713. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/types.ts +241 -0
  714. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace/watch-manager.ts +560 -0
  715. package/.forge/worktrees/pipeline-3156a8b3/lib/workspace-standalone.ts +911 -0
  716. package/.forge/worktrees/pipeline-3156a8b3/middleware.ts +51 -0
  717. package/.forge/worktrees/pipeline-3156a8b3/next.config.ts +26 -0
  718. package/.forge/worktrees/pipeline-3156a8b3/package.json +74 -0
  719. package/.forge/worktrees/pipeline-3156a8b3/pnpm-lock.yaml +3719 -0
  720. package/.forge/worktrees/pipeline-3156a8b3/pnpm-workspace.yaml +1 -0
  721. package/.forge/worktrees/pipeline-3156a8b3/postcss.config.mjs +7 -0
  722. package/.forge/worktrees/pipeline-3156a8b3/publish.sh +133 -0
  723. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/README.md +66 -0
  724. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/results/.gitignore +2 -0
  725. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/run.ts +635 -0
  726. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/01-text-utils/task.md +26 -0
  727. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  728. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  729. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/02-pagination/task.md +48 -0
  730. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  731. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  732. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  733. package/.forge/worktrees/pipeline-3156a8b3/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  734. package/.forge/worktrees/pipeline-3156a8b3/scripts/verify-usage.ts +178 -0
  735. package/.forge/worktrees/pipeline-3156a8b3/src/config/index.ts +129 -0
  736. package/.forge/worktrees/pipeline-3156a8b3/src/core/db/database.ts +259 -0
  737. package/.forge/worktrees/pipeline-3156a8b3/src/core/memory/strategy.ts +32 -0
  738. package/.forge/worktrees/pipeline-3156a8b3/src/core/providers/chat.ts +65 -0
  739. package/.forge/worktrees/pipeline-3156a8b3/src/core/providers/registry.ts +60 -0
  740. package/.forge/worktrees/pipeline-3156a8b3/src/core/session/manager.ts +190 -0
  741. package/.forge/worktrees/pipeline-3156a8b3/src/types/index.ts +129 -0
  742. package/.forge/worktrees/pipeline-3156a8b3/start.sh +31 -0
  743. package/.forge/worktrees/pipeline-3156a8b3/templates/smith-lead.json +45 -0
  744. package/.forge/worktrees/pipeline-3156a8b3/tsconfig.json +42 -0
  745. package/.forge/worktrees/pipeline-316c6574/CLAUDE.md +86 -0
  746. package/.forge/worktrees/pipeline-316c6574/README.md +136 -0
  747. package/.forge/worktrees/pipeline-316c6574/RELEASE_NOTES.md +11 -0
  748. package/.forge/worktrees/pipeline-316c6574/app/api/agents/route.ts +17 -0
  749. package/.forge/worktrees/pipeline-316c6574/app/api/auth/[...nextauth]/route.ts +3 -0
  750. package/.forge/worktrees/pipeline-316c6574/app/api/auth/verify/route.ts +46 -0
  751. package/.forge/worktrees/pipeline-316c6574/app/api/claude/[id]/route.ts +31 -0
  752. package/.forge/worktrees/pipeline-316c6574/app/api/claude/[id]/stream/route.ts +63 -0
  753. package/.forge/worktrees/pipeline-316c6574/app/api/claude/route.ts +28 -0
  754. package/.forge/worktrees/pipeline-316c6574/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  755. package/.forge/worktrees/pipeline-316c6574/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  756. package/.forge/worktrees/pipeline-316c6574/app/api/claude-sessions/[projectName]/route.ts +37 -0
  757. package/.forge/worktrees/pipeline-316c6574/app/api/claude-sessions/sync/route.ts +17 -0
  758. package/.forge/worktrees/pipeline-316c6574/app/api/claude-templates/route.ts +145 -0
  759. package/.forge/worktrees/pipeline-316c6574/app/api/code/route.ts +299 -0
  760. package/.forge/worktrees/pipeline-316c6574/app/api/delivery/[id]/route.ts +62 -0
  761. package/.forge/worktrees/pipeline-316c6574/app/api/delivery/route.ts +40 -0
  762. package/.forge/worktrees/pipeline-316c6574/app/api/detect-cli/route.ts +46 -0
  763. package/.forge/worktrees/pipeline-316c6574/app/api/docs/route.ts +176 -0
  764. package/.forge/worktrees/pipeline-316c6574/app/api/docs/sessions/route.ts +54 -0
  765. package/.forge/worktrees/pipeline-316c6574/app/api/favorites/route.ts +26 -0
  766. package/.forge/worktrees/pipeline-316c6574/app/api/flows/route.ts +6 -0
  767. package/.forge/worktrees/pipeline-316c6574/app/api/flows/run/route.ts +19 -0
  768. package/.forge/worktrees/pipeline-316c6574/app/api/git/route.ts +149 -0
  769. package/.forge/worktrees/pipeline-316c6574/app/api/help/route.ts +84 -0
  770. package/.forge/worktrees/pipeline-316c6574/app/api/issue-scanner/route.ts +116 -0
  771. package/.forge/worktrees/pipeline-316c6574/app/api/logs/route.ts +100 -0
  772. package/.forge/worktrees/pipeline-316c6574/app/api/mobile-chat/route.ts +115 -0
  773. package/.forge/worktrees/pipeline-316c6574/app/api/monitor/route.ts +74 -0
  774. package/.forge/worktrees/pipeline-316c6574/app/api/notifications/route.ts +42 -0
  775. package/.forge/worktrees/pipeline-316c6574/app/api/notify/test/route.ts +33 -0
  776. package/.forge/worktrees/pipeline-316c6574/app/api/online/route.ts +40 -0
  777. package/.forge/worktrees/pipeline-316c6574/app/api/pipelines/[id]/route.ts +41 -0
  778. package/.forge/worktrees/pipeline-316c6574/app/api/pipelines/route.ts +90 -0
  779. package/.forge/worktrees/pipeline-316c6574/app/api/plugins/route.ts +75 -0
  780. package/.forge/worktrees/pipeline-316c6574/app/api/preview/[...path]/route.ts +64 -0
  781. package/.forge/worktrees/pipeline-316c6574/app/api/preview/route.ts +156 -0
  782. package/.forge/worktrees/pipeline-316c6574/app/api/project-pipelines/route.ts +91 -0
  783. package/.forge/worktrees/pipeline-316c6574/app/api/project-sessions/route.ts +61 -0
  784. package/.forge/worktrees/pipeline-316c6574/app/api/projects/route.ts +26 -0
  785. package/.forge/worktrees/pipeline-316c6574/app/api/sessions/[id]/chat/route.ts +64 -0
  786. package/.forge/worktrees/pipeline-316c6574/app/api/sessions/[id]/messages/route.ts +9 -0
  787. package/.forge/worktrees/pipeline-316c6574/app/api/sessions/[id]/route.ts +17 -0
  788. package/.forge/worktrees/pipeline-316c6574/app/api/sessions/route.ts +20 -0
  789. package/.forge/worktrees/pipeline-316c6574/app/api/settings/route.ts +64 -0
  790. package/.forge/worktrees/pipeline-316c6574/app/api/skills/local/route.ts +228 -0
  791. package/.forge/worktrees/pipeline-316c6574/app/api/skills/route.ts +182 -0
  792. package/.forge/worktrees/pipeline-316c6574/app/api/smith-templates/route.ts +81 -0
  793. package/.forge/worktrees/pipeline-316c6574/app/api/status/route.ts +12 -0
  794. package/.forge/worktrees/pipeline-316c6574/app/api/tabs/route.ts +25 -0
  795. package/.forge/worktrees/pipeline-316c6574/app/api/tasks/[id]/route.ts +51 -0
  796. package/.forge/worktrees/pipeline-316c6574/app/api/tasks/[id]/stream/route.ts +77 -0
  797. package/.forge/worktrees/pipeline-316c6574/app/api/tasks/link/route.ts +37 -0
  798. package/.forge/worktrees/pipeline-316c6574/app/api/tasks/route.ts +44 -0
  799. package/.forge/worktrees/pipeline-316c6574/app/api/tasks/session/route.ts +14 -0
  800. package/.forge/worktrees/pipeline-316c6574/app/api/telegram/route.ts +23 -0
  801. package/.forge/worktrees/pipeline-316c6574/app/api/templates/route.ts +6 -0
  802. package/.forge/worktrees/pipeline-316c6574/app/api/terminal-bell/route.ts +35 -0
  803. package/.forge/worktrees/pipeline-316c6574/app/api/terminal-cwd/route.ts +19 -0
  804. package/.forge/worktrees/pipeline-316c6574/app/api/terminal-state/route.ts +15 -0
  805. package/.forge/worktrees/pipeline-316c6574/app/api/tunnel/route.ts +26 -0
  806. package/.forge/worktrees/pipeline-316c6574/app/api/upgrade/route.ts +43 -0
  807. package/.forge/worktrees/pipeline-316c6574/app/api/usage/route.ts +20 -0
  808. package/.forge/worktrees/pipeline-316c6574/app/api/version/route.ts +78 -0
  809. package/.forge/worktrees/pipeline-316c6574/app/api/watchers/route.ts +33 -0
  810. package/.forge/worktrees/pipeline-316c6574/app/api/workspace/[id]/agents/route.ts +35 -0
  811. package/.forge/worktrees/pipeline-316c6574/app/api/workspace/[id]/memory/route.ts +23 -0
  812. package/.forge/worktrees/pipeline-316c6574/app/api/workspace/[id]/smith/route.ts +22 -0
  813. package/.forge/worktrees/pipeline-316c6574/app/api/workspace/[id]/stream/route.ts +28 -0
  814. package/.forge/worktrees/pipeline-316c6574/app/api/workspace/route.ts +100 -0
  815. package/.forge/worktrees/pipeline-316c6574/app/global-error.tsx +21 -0
  816. package/.forge/worktrees/pipeline-316c6574/app/globals.css +52 -0
  817. package/.forge/worktrees/pipeline-316c6574/app/icon.ico +0 -0
  818. package/.forge/worktrees/pipeline-316c6574/app/icon.png +0 -0
  819. package/.forge/worktrees/pipeline-316c6574/app/icon.svg +106 -0
  820. package/.forge/worktrees/pipeline-316c6574/app/layout.tsx +17 -0
  821. package/.forge/worktrees/pipeline-316c6574/app/login/LoginForm.tsx +96 -0
  822. package/.forge/worktrees/pipeline-316c6574/app/login/page.tsx +10 -0
  823. package/.forge/worktrees/pipeline-316c6574/app/mobile/page.tsx +9 -0
  824. package/.forge/worktrees/pipeline-316c6574/app/page.tsx +21 -0
  825. package/.forge/worktrees/pipeline-316c6574/bin/forge-server.mjs +484 -0
  826. package/.forge/worktrees/pipeline-316c6574/check-forge-status.sh +71 -0
  827. package/.forge/worktrees/pipeline-316c6574/cli/mw.ts +579 -0
  828. package/.forge/worktrees/pipeline-316c6574/components/BrowserPanel.tsx +175 -0
  829. package/.forge/worktrees/pipeline-316c6574/components/ChatPanel.tsx +191 -0
  830. package/.forge/worktrees/pipeline-316c6574/components/ClaudeTerminal.tsx +267 -0
  831. package/.forge/worktrees/pipeline-316c6574/components/CodeViewer.tsx +787 -0
  832. package/.forge/worktrees/pipeline-316c6574/components/ConversationEditor.tsx +411 -0
  833. package/.forge/worktrees/pipeline-316c6574/components/ConversationGraphView.tsx +347 -0
  834. package/.forge/worktrees/pipeline-316c6574/components/ConversationTerminalView.tsx +303 -0
  835. package/.forge/worktrees/pipeline-316c6574/components/Dashboard.tsx +807 -0
  836. package/.forge/worktrees/pipeline-316c6574/components/DashboardWrapper.tsx +9 -0
  837. package/.forge/worktrees/pipeline-316c6574/components/DeliveryFlowEditor.tsx +491 -0
  838. package/.forge/worktrees/pipeline-316c6574/components/DeliveryList.tsx +230 -0
  839. package/.forge/worktrees/pipeline-316c6574/components/DeliveryWorkspace.tsx +589 -0
  840. package/.forge/worktrees/pipeline-316c6574/components/DocTerminal.tsx +187 -0
  841. package/.forge/worktrees/pipeline-316c6574/components/DocsViewer.tsx +574 -0
  842. package/.forge/worktrees/pipeline-316c6574/components/HelpDialog.tsx +169 -0
  843. package/.forge/worktrees/pipeline-316c6574/components/HelpTerminal.tsx +141 -0
  844. package/.forge/worktrees/pipeline-316c6574/components/InlinePipelineView.tsx +111 -0
  845. package/.forge/worktrees/pipeline-316c6574/components/LogViewer.tsx +194 -0
  846. package/.forge/worktrees/pipeline-316c6574/components/MarkdownContent.tsx +73 -0
  847. package/.forge/worktrees/pipeline-316c6574/components/MobileView.tsx +385 -0
  848. package/.forge/worktrees/pipeline-316c6574/components/MonitorPanel.tsx +122 -0
  849. package/.forge/worktrees/pipeline-316c6574/components/NewSessionModal.tsx +93 -0
  850. package/.forge/worktrees/pipeline-316c6574/components/NewTaskModal.tsx +492 -0
  851. package/.forge/worktrees/pipeline-316c6574/components/PipelineEditor.tsx +570 -0
  852. package/.forge/worktrees/pipeline-316c6574/components/PipelineView.tsx +1018 -0
  853. package/.forge/worktrees/pipeline-316c6574/components/PluginsPanel.tsx +472 -0
  854. package/.forge/worktrees/pipeline-316c6574/components/ProjectDetail.tsx +1618 -0
  855. package/.forge/worktrees/pipeline-316c6574/components/ProjectList.tsx +108 -0
  856. package/.forge/worktrees/pipeline-316c6574/components/ProjectManager.tsx +401 -0
  857. package/.forge/worktrees/pipeline-316c6574/components/SessionList.tsx +74 -0
  858. package/.forge/worktrees/pipeline-316c6574/components/SessionView.tsx +726 -0
  859. package/.forge/worktrees/pipeline-316c6574/components/SettingsModal.tsx +1647 -0
  860. package/.forge/worktrees/pipeline-316c6574/components/SkillsPanel.tsx +969 -0
  861. package/.forge/worktrees/pipeline-316c6574/components/StatusBar.tsx +99 -0
  862. package/.forge/worktrees/pipeline-316c6574/components/TabBar.tsx +46 -0
  863. package/.forge/worktrees/pipeline-316c6574/components/TaskBoard.tsx +113 -0
  864. package/.forge/worktrees/pipeline-316c6574/components/TaskDetail.tsx +372 -0
  865. package/.forge/worktrees/pipeline-316c6574/components/TerminalLauncher.tsx +398 -0
  866. package/.forge/worktrees/pipeline-316c6574/components/TunnelToggle.tsx +206 -0
  867. package/.forge/worktrees/pipeline-316c6574/components/UsagePanel.tsx +207 -0
  868. package/.forge/worktrees/pipeline-316c6574/components/WebTerminal.tsx +1683 -0
  869. package/.forge/worktrees/pipeline-316c6574/components/WorkspaceTree.tsx +221 -0
  870. package/.forge/worktrees/pipeline-316c6574/components/WorkspaceView.tsx +4048 -0
  871. package/.forge/worktrees/pipeline-316c6574/dev-test.sh +5 -0
  872. package/.forge/worktrees/pipeline-316c6574/docs/Forge_Memory_Layer_Design.docx +0 -0
  873. package/.forge/worktrees/pipeline-316c6574/docs/Forge_Strategy_Research_2026.docx +0 -0
  874. package/.forge/worktrees/pipeline-316c6574/docs/LOCAL-DEPLOY.md +144 -0
  875. package/.forge/worktrees/pipeline-316c6574/docs/roadmap-multi-agent-workflow.md +330 -0
  876. package/.forge/worktrees/pipeline-316c6574/forge-logo.png +0 -0
  877. package/.forge/worktrees/pipeline-316c6574/forge-logo.svg +106 -0
  878. package/.forge/worktrees/pipeline-316c6574/hooks/useSidebarResize.ts +52 -0
  879. package/.forge/worktrees/pipeline-316c6574/install.sh +29 -0
  880. package/.forge/worktrees/pipeline-316c6574/instrumentation.ts +35 -0
  881. package/.forge/worktrees/pipeline-316c6574/lib/agents/claude-adapter.ts +104 -0
  882. package/.forge/worktrees/pipeline-316c6574/lib/agents/generic-adapter.ts +64 -0
  883. package/.forge/worktrees/pipeline-316c6574/lib/agents/index.ts +245 -0
  884. package/.forge/worktrees/pipeline-316c6574/lib/agents/types.ts +70 -0
  885. package/.forge/worktrees/pipeline-316c6574/lib/artifacts.ts +106 -0
  886. package/.forge/worktrees/pipeline-316c6574/lib/auth.ts +62 -0
  887. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/docker.yaml +70 -0
  888. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/http.yaml +66 -0
  889. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/jenkins.yaml +92 -0
  890. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/llm-vision.yaml +85 -0
  891. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/playwright.yaml +111 -0
  892. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/shell-command.yaml +60 -0
  893. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/slack.yaml +48 -0
  894. package/.forge/worktrees/pipeline-316c6574/lib/builtin-plugins/webhook.yaml +56 -0
  895. package/.forge/worktrees/pipeline-316c6574/lib/claude-process.ts +361 -0
  896. package/.forge/worktrees/pipeline-316c6574/lib/claude-sessions.ts +266 -0
  897. package/.forge/worktrees/pipeline-316c6574/lib/claude-templates.ts +227 -0
  898. package/.forge/worktrees/pipeline-316c6574/lib/cloudflared.ts +424 -0
  899. package/.forge/worktrees/pipeline-316c6574/lib/crypto.ts +67 -0
  900. package/.forge/worktrees/pipeline-316c6574/lib/delivery.ts +787 -0
  901. package/.forge/worktrees/pipeline-316c6574/lib/dirs.ts +99 -0
  902. package/.forge/worktrees/pipeline-316c6574/lib/flows.ts +86 -0
  903. package/.forge/worktrees/pipeline-316c6574/lib/forge-mcp-server.ts +717 -0
  904. package/.forge/worktrees/pipeline-316c6574/lib/forge-skills/forge-inbox.md +38 -0
  905. package/.forge/worktrees/pipeline-316c6574/lib/forge-skills/forge-send.md +47 -0
  906. package/.forge/worktrees/pipeline-316c6574/lib/forge-skills/forge-status.md +32 -0
  907. package/.forge/worktrees/pipeline-316c6574/lib/forge-skills/forge-workspace-sync.md +37 -0
  908. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/00-overview.md +40 -0
  909. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/01-settings.md +194 -0
  910. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/02-telegram.md +41 -0
  911. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/03-tunnel.md +31 -0
  912. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/04-tasks.md +52 -0
  913. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/05-pipelines.md +460 -0
  914. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/06-skills.md +43 -0
  915. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/07-projects.md +73 -0
  916. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/08-rules.md +53 -0
  917. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/09-issue-autofix.md +55 -0
  918. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/10-troubleshooting.md +89 -0
  919. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/11-workspace.md +810 -0
  920. package/.forge/worktrees/pipeline-316c6574/lib/help-docs/CLAUDE.md +62 -0
  921. package/.forge/worktrees/pipeline-316c6574/lib/init.ts +266 -0
  922. package/.forge/worktrees/pipeline-316c6574/lib/issue-scanner.ts +298 -0
  923. package/.forge/worktrees/pipeline-316c6574/lib/logger.ts +79 -0
  924. package/.forge/worktrees/pipeline-316c6574/lib/notifications.ts +75 -0
  925. package/.forge/worktrees/pipeline-316c6574/lib/notify.ts +108 -0
  926. package/.forge/worktrees/pipeline-316c6574/lib/password.ts +97 -0
  927. package/.forge/worktrees/pipeline-316c6574/lib/pipeline-scheduler.ts +373 -0
  928. package/.forge/worktrees/pipeline-316c6574/lib/pipeline.ts +1441 -0
  929. package/.forge/worktrees/pipeline-316c6574/lib/plugins/executor.ts +347 -0
  930. package/.forge/worktrees/pipeline-316c6574/lib/plugins/registry.ts +228 -0
  931. package/.forge/worktrees/pipeline-316c6574/lib/plugins/types.ts +103 -0
  932. package/.forge/worktrees/pipeline-316c6574/lib/project-sessions.ts +53 -0
  933. package/.forge/worktrees/pipeline-316c6574/lib/projects.ts +86 -0
  934. package/.forge/worktrees/pipeline-316c6574/lib/session-manager.ts +156 -0
  935. package/.forge/worktrees/pipeline-316c6574/lib/session-utils.ts +53 -0
  936. package/.forge/worktrees/pipeline-316c6574/lib/session-watcher.ts +345 -0
  937. package/.forge/worktrees/pipeline-316c6574/lib/settings.ts +195 -0
  938. package/.forge/worktrees/pipeline-316c6574/lib/skills.ts +458 -0
  939. package/.forge/worktrees/pipeline-316c6574/lib/task-manager.ts +949 -0
  940. package/.forge/worktrees/pipeline-316c6574/lib/telegram-bot.ts +1477 -0
  941. package/.forge/worktrees/pipeline-316c6574/lib/telegram-standalone.ts +83 -0
  942. package/.forge/worktrees/pipeline-316c6574/lib/terminal-server.ts +70 -0
  943. package/.forge/worktrees/pipeline-316c6574/lib/terminal-standalone.ts +421 -0
  944. package/.forge/worktrees/pipeline-316c6574/lib/usage-scanner.ts +249 -0
  945. package/.forge/worktrees/pipeline-316c6574/lib/workspace/__tests__/state-machine.test.ts +388 -0
  946. package/.forge/worktrees/pipeline-316c6574/lib/workspace/__tests__/workspace.test.ts +311 -0
  947. package/.forge/worktrees/pipeline-316c6574/lib/workspace/agent-bus.ts +416 -0
  948. package/.forge/worktrees/pipeline-316c6574/lib/workspace/agent-worker.ts +655 -0
  949. package/.forge/worktrees/pipeline-316c6574/lib/workspace/backends/api-backend.ts +262 -0
  950. package/.forge/worktrees/pipeline-316c6574/lib/workspace/backends/cli-backend.ts +491 -0
  951. package/.forge/worktrees/pipeline-316c6574/lib/workspace/index.ts +82 -0
  952. package/.forge/worktrees/pipeline-316c6574/lib/workspace/manager.ts +136 -0
  953. package/.forge/worktrees/pipeline-316c6574/lib/workspace/orchestrator.ts +3400 -0
  954. package/.forge/worktrees/pipeline-316c6574/lib/workspace/persistence.ts +309 -0
  955. package/.forge/worktrees/pipeline-316c6574/lib/workspace/presets.ts +649 -0
  956. package/.forge/worktrees/pipeline-316c6574/lib/workspace/requests.ts +287 -0
  957. package/.forge/worktrees/pipeline-316c6574/lib/workspace/session-monitor.ts +240 -0
  958. package/.forge/worktrees/pipeline-316c6574/lib/workspace/skill-installer.ts +275 -0
  959. package/.forge/worktrees/pipeline-316c6574/lib/workspace/smith-memory.ts +498 -0
  960. package/.forge/worktrees/pipeline-316c6574/lib/workspace/types.ts +241 -0
  961. package/.forge/worktrees/pipeline-316c6574/lib/workspace/watch-manager.ts +560 -0
  962. package/.forge/worktrees/pipeline-316c6574/lib/workspace-standalone.ts +911 -0
  963. package/.forge/worktrees/pipeline-316c6574/middleware.ts +51 -0
  964. package/.forge/worktrees/pipeline-316c6574/next.config.ts +26 -0
  965. package/.forge/worktrees/pipeline-316c6574/package.json +74 -0
  966. package/.forge/worktrees/pipeline-316c6574/pnpm-lock.yaml +3719 -0
  967. package/.forge/worktrees/pipeline-316c6574/pnpm-workspace.yaml +1 -0
  968. package/.forge/worktrees/pipeline-316c6574/postcss.config.mjs +7 -0
  969. package/.forge/worktrees/pipeline-316c6574/publish.sh +133 -0
  970. package/.forge/worktrees/pipeline-316c6574/scripts/bench/README.md +66 -0
  971. package/.forge/worktrees/pipeline-316c6574/scripts/bench/results/.gitignore +2 -0
  972. package/.forge/worktrees/pipeline-316c6574/scripts/bench/run.ts +635 -0
  973. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/01-text-utils/task.md +26 -0
  974. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  975. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  976. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/02-pagination/task.md +48 -0
  977. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  978. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  979. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  980. package/.forge/worktrees/pipeline-316c6574/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  981. package/.forge/worktrees/pipeline-316c6574/scripts/verify-usage.ts +178 -0
  982. package/.forge/worktrees/pipeline-316c6574/src/config/index.ts +129 -0
  983. package/.forge/worktrees/pipeline-316c6574/src/core/db/database.ts +259 -0
  984. package/.forge/worktrees/pipeline-316c6574/src/core/memory/strategy.ts +32 -0
  985. package/.forge/worktrees/pipeline-316c6574/src/core/providers/chat.ts +65 -0
  986. package/.forge/worktrees/pipeline-316c6574/src/core/providers/registry.ts +60 -0
  987. package/.forge/worktrees/pipeline-316c6574/src/core/session/manager.ts +190 -0
  988. package/.forge/worktrees/pipeline-316c6574/src/types/index.ts +129 -0
  989. package/.forge/worktrees/pipeline-316c6574/start.sh +31 -0
  990. package/.forge/worktrees/pipeline-316c6574/templates/smith-lead.json +45 -0
  991. package/.forge/worktrees/pipeline-316c6574/tsconfig.json +42 -0
  992. package/.forge/worktrees/pipeline-44a94121/CLAUDE.md +86 -0
  993. package/.forge/worktrees/pipeline-44a94121/README.md +136 -0
  994. package/.forge/worktrees/pipeline-44a94121/RELEASE_NOTES.md +11 -0
  995. package/.forge/worktrees/pipeline-44a94121/app/api/agents/route.ts +17 -0
  996. package/.forge/worktrees/pipeline-44a94121/app/api/auth/[...nextauth]/route.ts +3 -0
  997. package/.forge/worktrees/pipeline-44a94121/app/api/auth/verify/route.ts +46 -0
  998. package/.forge/worktrees/pipeline-44a94121/app/api/claude/[id]/route.ts +31 -0
  999. package/.forge/worktrees/pipeline-44a94121/app/api/claude/[id]/stream/route.ts +63 -0
  1000. package/.forge/worktrees/pipeline-44a94121/app/api/claude/route.ts +28 -0
  1001. package/.forge/worktrees/pipeline-44a94121/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  1002. package/.forge/worktrees/pipeline-44a94121/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  1003. package/.forge/worktrees/pipeline-44a94121/app/api/claude-sessions/[projectName]/route.ts +37 -0
  1004. package/.forge/worktrees/pipeline-44a94121/app/api/claude-sessions/sync/route.ts +17 -0
  1005. package/.forge/worktrees/pipeline-44a94121/app/api/claude-templates/route.ts +145 -0
  1006. package/.forge/worktrees/pipeline-44a94121/app/api/code/route.ts +299 -0
  1007. package/.forge/worktrees/pipeline-44a94121/app/api/delivery/[id]/route.ts +62 -0
  1008. package/.forge/worktrees/pipeline-44a94121/app/api/delivery/route.ts +40 -0
  1009. package/.forge/worktrees/pipeline-44a94121/app/api/detect-cli/route.ts +46 -0
  1010. package/.forge/worktrees/pipeline-44a94121/app/api/docs/route.ts +176 -0
  1011. package/.forge/worktrees/pipeline-44a94121/app/api/docs/sessions/route.ts +54 -0
  1012. package/.forge/worktrees/pipeline-44a94121/app/api/favorites/route.ts +26 -0
  1013. package/.forge/worktrees/pipeline-44a94121/app/api/flows/route.ts +6 -0
  1014. package/.forge/worktrees/pipeline-44a94121/app/api/flows/run/route.ts +19 -0
  1015. package/.forge/worktrees/pipeline-44a94121/app/api/git/route.ts +149 -0
  1016. package/.forge/worktrees/pipeline-44a94121/app/api/help/route.ts +84 -0
  1017. package/.forge/worktrees/pipeline-44a94121/app/api/issue-scanner/route.ts +116 -0
  1018. package/.forge/worktrees/pipeline-44a94121/app/api/logs/route.ts +100 -0
  1019. package/.forge/worktrees/pipeline-44a94121/app/api/mobile-chat/route.ts +115 -0
  1020. package/.forge/worktrees/pipeline-44a94121/app/api/monitor/route.ts +74 -0
  1021. package/.forge/worktrees/pipeline-44a94121/app/api/notifications/route.ts +42 -0
  1022. package/.forge/worktrees/pipeline-44a94121/app/api/notify/test/route.ts +33 -0
  1023. package/.forge/worktrees/pipeline-44a94121/app/api/online/route.ts +40 -0
  1024. package/.forge/worktrees/pipeline-44a94121/app/api/pipelines/[id]/route.ts +41 -0
  1025. package/.forge/worktrees/pipeline-44a94121/app/api/pipelines/route.ts +90 -0
  1026. package/.forge/worktrees/pipeline-44a94121/app/api/plugins/route.ts +75 -0
  1027. package/.forge/worktrees/pipeline-44a94121/app/api/preview/[...path]/route.ts +64 -0
  1028. package/.forge/worktrees/pipeline-44a94121/app/api/preview/route.ts +156 -0
  1029. package/.forge/worktrees/pipeline-44a94121/app/api/project-pipelines/route.ts +91 -0
  1030. package/.forge/worktrees/pipeline-44a94121/app/api/project-sessions/route.ts +61 -0
  1031. package/.forge/worktrees/pipeline-44a94121/app/api/projects/route.ts +26 -0
  1032. package/.forge/worktrees/pipeline-44a94121/app/api/sessions/[id]/chat/route.ts +64 -0
  1033. package/.forge/worktrees/pipeline-44a94121/app/api/sessions/[id]/messages/route.ts +9 -0
  1034. package/.forge/worktrees/pipeline-44a94121/app/api/sessions/[id]/route.ts +17 -0
  1035. package/.forge/worktrees/pipeline-44a94121/app/api/sessions/route.ts +20 -0
  1036. package/.forge/worktrees/pipeline-44a94121/app/api/settings/route.ts +64 -0
  1037. package/.forge/worktrees/pipeline-44a94121/app/api/skills/local/route.ts +228 -0
  1038. package/.forge/worktrees/pipeline-44a94121/app/api/skills/route.ts +182 -0
  1039. package/.forge/worktrees/pipeline-44a94121/app/api/smith-templates/route.ts +81 -0
  1040. package/.forge/worktrees/pipeline-44a94121/app/api/status/route.ts +12 -0
  1041. package/.forge/worktrees/pipeline-44a94121/app/api/tabs/route.ts +25 -0
  1042. package/.forge/worktrees/pipeline-44a94121/app/api/tasks/[id]/route.ts +51 -0
  1043. package/.forge/worktrees/pipeline-44a94121/app/api/tasks/[id]/stream/route.ts +77 -0
  1044. package/.forge/worktrees/pipeline-44a94121/app/api/tasks/link/route.ts +37 -0
  1045. package/.forge/worktrees/pipeline-44a94121/app/api/tasks/route.ts +44 -0
  1046. package/.forge/worktrees/pipeline-44a94121/app/api/tasks/session/route.ts +14 -0
  1047. package/.forge/worktrees/pipeline-44a94121/app/api/telegram/route.ts +23 -0
  1048. package/.forge/worktrees/pipeline-44a94121/app/api/templates/route.ts +6 -0
  1049. package/.forge/worktrees/pipeline-44a94121/app/api/terminal-bell/route.ts +35 -0
  1050. package/.forge/worktrees/pipeline-44a94121/app/api/terminal-cwd/route.ts +19 -0
  1051. package/.forge/worktrees/pipeline-44a94121/app/api/terminal-state/route.ts +15 -0
  1052. package/.forge/worktrees/pipeline-44a94121/app/api/tunnel/route.ts +26 -0
  1053. package/.forge/worktrees/pipeline-44a94121/app/api/upgrade/route.ts +43 -0
  1054. package/.forge/worktrees/pipeline-44a94121/app/api/usage/route.ts +20 -0
  1055. package/.forge/worktrees/pipeline-44a94121/app/api/version/route.ts +78 -0
  1056. package/.forge/worktrees/pipeline-44a94121/app/api/watchers/route.ts +33 -0
  1057. package/.forge/worktrees/pipeline-44a94121/app/api/workspace/[id]/agents/route.ts +35 -0
  1058. package/.forge/worktrees/pipeline-44a94121/app/api/workspace/[id]/memory/route.ts +23 -0
  1059. package/.forge/worktrees/pipeline-44a94121/app/api/workspace/[id]/smith/route.ts +22 -0
  1060. package/.forge/worktrees/pipeline-44a94121/app/api/workspace/[id]/stream/route.ts +28 -0
  1061. package/.forge/worktrees/pipeline-44a94121/app/api/workspace/route.ts +100 -0
  1062. package/.forge/worktrees/pipeline-44a94121/app/global-error.tsx +21 -0
  1063. package/.forge/worktrees/pipeline-44a94121/app/globals.css +52 -0
  1064. package/.forge/worktrees/pipeline-44a94121/app/icon.ico +0 -0
  1065. package/.forge/worktrees/pipeline-44a94121/app/icon.png +0 -0
  1066. package/.forge/worktrees/pipeline-44a94121/app/icon.svg +106 -0
  1067. package/.forge/worktrees/pipeline-44a94121/app/layout.tsx +17 -0
  1068. package/.forge/worktrees/pipeline-44a94121/app/login/LoginForm.tsx +96 -0
  1069. package/.forge/worktrees/pipeline-44a94121/app/login/page.tsx +10 -0
  1070. package/.forge/worktrees/pipeline-44a94121/app/mobile/page.tsx +9 -0
  1071. package/.forge/worktrees/pipeline-44a94121/app/page.tsx +21 -0
  1072. package/.forge/worktrees/pipeline-44a94121/bin/forge-server.mjs +484 -0
  1073. package/.forge/worktrees/pipeline-44a94121/check-forge-status.sh +71 -0
  1074. package/.forge/worktrees/pipeline-44a94121/cli/mw.ts +579 -0
  1075. package/.forge/worktrees/pipeline-44a94121/components/BrowserPanel.tsx +175 -0
  1076. package/.forge/worktrees/pipeline-44a94121/components/ChatPanel.tsx +191 -0
  1077. package/.forge/worktrees/pipeline-44a94121/components/ClaudeTerminal.tsx +267 -0
  1078. package/.forge/worktrees/pipeline-44a94121/components/CodeViewer.tsx +787 -0
  1079. package/.forge/worktrees/pipeline-44a94121/components/ConversationEditor.tsx +411 -0
  1080. package/.forge/worktrees/pipeline-44a94121/components/ConversationGraphView.tsx +347 -0
  1081. package/.forge/worktrees/pipeline-44a94121/components/ConversationTerminalView.tsx +303 -0
  1082. package/.forge/worktrees/pipeline-44a94121/components/Dashboard.tsx +807 -0
  1083. package/.forge/worktrees/pipeline-44a94121/components/DashboardWrapper.tsx +9 -0
  1084. package/.forge/worktrees/pipeline-44a94121/components/DeliveryFlowEditor.tsx +491 -0
  1085. package/.forge/worktrees/pipeline-44a94121/components/DeliveryList.tsx +230 -0
  1086. package/.forge/worktrees/pipeline-44a94121/components/DeliveryWorkspace.tsx +589 -0
  1087. package/.forge/worktrees/pipeline-44a94121/components/DocTerminal.tsx +187 -0
  1088. package/.forge/worktrees/pipeline-44a94121/components/DocsViewer.tsx +574 -0
  1089. package/.forge/worktrees/pipeline-44a94121/components/HelpDialog.tsx +169 -0
  1090. package/.forge/worktrees/pipeline-44a94121/components/HelpTerminal.tsx +141 -0
  1091. package/.forge/worktrees/pipeline-44a94121/components/InlinePipelineView.tsx +111 -0
  1092. package/.forge/worktrees/pipeline-44a94121/components/LogViewer.tsx +194 -0
  1093. package/.forge/worktrees/pipeline-44a94121/components/MarkdownContent.tsx +73 -0
  1094. package/.forge/worktrees/pipeline-44a94121/components/MobileView.tsx +385 -0
  1095. package/.forge/worktrees/pipeline-44a94121/components/MonitorPanel.tsx +122 -0
  1096. package/.forge/worktrees/pipeline-44a94121/components/NewSessionModal.tsx +93 -0
  1097. package/.forge/worktrees/pipeline-44a94121/components/NewTaskModal.tsx +492 -0
  1098. package/.forge/worktrees/pipeline-44a94121/components/PipelineEditor.tsx +570 -0
  1099. package/.forge/worktrees/pipeline-44a94121/components/PipelineView.tsx +1018 -0
  1100. package/.forge/worktrees/pipeline-44a94121/components/PluginsPanel.tsx +472 -0
  1101. package/.forge/worktrees/pipeline-44a94121/components/ProjectDetail.tsx +1618 -0
  1102. package/.forge/worktrees/pipeline-44a94121/components/ProjectList.tsx +108 -0
  1103. package/.forge/worktrees/pipeline-44a94121/components/ProjectManager.tsx +401 -0
  1104. package/.forge/worktrees/pipeline-44a94121/components/SessionList.tsx +74 -0
  1105. package/.forge/worktrees/pipeline-44a94121/components/SessionView.tsx +726 -0
  1106. package/.forge/worktrees/pipeline-44a94121/components/SettingsModal.tsx +1647 -0
  1107. package/.forge/worktrees/pipeline-44a94121/components/SkillsPanel.tsx +969 -0
  1108. package/.forge/worktrees/pipeline-44a94121/components/StatusBar.tsx +99 -0
  1109. package/.forge/worktrees/pipeline-44a94121/components/TabBar.tsx +46 -0
  1110. package/.forge/worktrees/pipeline-44a94121/components/TaskBoard.tsx +113 -0
  1111. package/.forge/worktrees/pipeline-44a94121/components/TaskDetail.tsx +372 -0
  1112. package/.forge/worktrees/pipeline-44a94121/components/TerminalLauncher.tsx +398 -0
  1113. package/.forge/worktrees/pipeline-44a94121/components/TunnelToggle.tsx +206 -0
  1114. package/.forge/worktrees/pipeline-44a94121/components/UsagePanel.tsx +207 -0
  1115. package/.forge/worktrees/pipeline-44a94121/components/WebTerminal.tsx +1683 -0
  1116. package/.forge/worktrees/pipeline-44a94121/components/WorkspaceTree.tsx +221 -0
  1117. package/.forge/worktrees/pipeline-44a94121/components/WorkspaceView.tsx +4048 -0
  1118. package/.forge/worktrees/pipeline-44a94121/dev-test.sh +5 -0
  1119. package/.forge/worktrees/pipeline-44a94121/docs/Forge_Memory_Layer_Design.docx +0 -0
  1120. package/.forge/worktrees/pipeline-44a94121/docs/Forge_Strategy_Research_2026.docx +0 -0
  1121. package/.forge/worktrees/pipeline-44a94121/docs/LOCAL-DEPLOY.md +144 -0
  1122. package/.forge/worktrees/pipeline-44a94121/docs/roadmap-multi-agent-workflow.md +330 -0
  1123. package/.forge/worktrees/pipeline-44a94121/forge-logo.png +0 -0
  1124. package/.forge/worktrees/pipeline-44a94121/forge-logo.svg +106 -0
  1125. package/.forge/worktrees/pipeline-44a94121/hooks/useSidebarResize.ts +52 -0
  1126. package/.forge/worktrees/pipeline-44a94121/install.sh +29 -0
  1127. package/.forge/worktrees/pipeline-44a94121/instrumentation.ts +35 -0
  1128. package/.forge/worktrees/pipeline-44a94121/lib/agents/claude-adapter.ts +104 -0
  1129. package/.forge/worktrees/pipeline-44a94121/lib/agents/generic-adapter.ts +64 -0
  1130. package/.forge/worktrees/pipeline-44a94121/lib/agents/index.ts +245 -0
  1131. package/.forge/worktrees/pipeline-44a94121/lib/agents/types.ts +70 -0
  1132. package/.forge/worktrees/pipeline-44a94121/lib/artifacts.ts +106 -0
  1133. package/.forge/worktrees/pipeline-44a94121/lib/auth.ts +62 -0
  1134. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/docker.yaml +70 -0
  1135. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/http.yaml +66 -0
  1136. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/jenkins.yaml +92 -0
  1137. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/llm-vision.yaml +85 -0
  1138. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/playwright.yaml +111 -0
  1139. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/shell-command.yaml +60 -0
  1140. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/slack.yaml +48 -0
  1141. package/.forge/worktrees/pipeline-44a94121/lib/builtin-plugins/webhook.yaml +56 -0
  1142. package/.forge/worktrees/pipeline-44a94121/lib/claude-process.ts +351 -0
  1143. package/.forge/worktrees/pipeline-44a94121/lib/claude-sessions.ts +266 -0
  1144. package/.forge/worktrees/pipeline-44a94121/lib/claude-templates.ts +227 -0
  1145. package/.forge/worktrees/pipeline-44a94121/lib/cloudflared.ts +424 -0
  1146. package/.forge/worktrees/pipeline-44a94121/lib/crypto.ts +67 -0
  1147. package/.forge/worktrees/pipeline-44a94121/lib/delivery.ts +787 -0
  1148. package/.forge/worktrees/pipeline-44a94121/lib/dirs.ts +99 -0
  1149. package/.forge/worktrees/pipeline-44a94121/lib/flows.ts +86 -0
  1150. package/.forge/worktrees/pipeline-44a94121/lib/forge-mcp-server.ts +717 -0
  1151. package/.forge/worktrees/pipeline-44a94121/lib/forge-skills/forge-inbox.md +38 -0
  1152. package/.forge/worktrees/pipeline-44a94121/lib/forge-skills/forge-send.md +47 -0
  1153. package/.forge/worktrees/pipeline-44a94121/lib/forge-skills/forge-status.md +32 -0
  1154. package/.forge/worktrees/pipeline-44a94121/lib/forge-skills/forge-workspace-sync.md +37 -0
  1155. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/00-overview.md +40 -0
  1156. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/01-settings.md +194 -0
  1157. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/02-telegram.md +41 -0
  1158. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/03-tunnel.md +31 -0
  1159. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/04-tasks.md +52 -0
  1160. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/05-pipelines.md +460 -0
  1161. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/06-skills.md +43 -0
  1162. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/07-projects.md +73 -0
  1163. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/08-rules.md +53 -0
  1164. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/09-issue-autofix.md +55 -0
  1165. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/10-troubleshooting.md +89 -0
  1166. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/11-workspace.md +810 -0
  1167. package/.forge/worktrees/pipeline-44a94121/lib/help-docs/CLAUDE.md +62 -0
  1168. package/.forge/worktrees/pipeline-44a94121/lib/init.ts +266 -0
  1169. package/.forge/worktrees/pipeline-44a94121/lib/issue-scanner.ts +298 -0
  1170. package/.forge/worktrees/pipeline-44a94121/lib/logger.ts +79 -0
  1171. package/.forge/worktrees/pipeline-44a94121/lib/notifications.ts +75 -0
  1172. package/.forge/worktrees/pipeline-44a94121/lib/notify.ts +108 -0
  1173. package/.forge/worktrees/pipeline-44a94121/lib/password.ts +97 -0
  1174. package/.forge/worktrees/pipeline-44a94121/lib/pipeline-scheduler.ts +373 -0
  1175. package/.forge/worktrees/pipeline-44a94121/lib/pipeline.ts +1441 -0
  1176. package/.forge/worktrees/pipeline-44a94121/lib/plugins/executor.ts +347 -0
  1177. package/.forge/worktrees/pipeline-44a94121/lib/plugins/registry.ts +228 -0
  1178. package/.forge/worktrees/pipeline-44a94121/lib/plugins/types.ts +103 -0
  1179. package/.forge/worktrees/pipeline-44a94121/lib/project-sessions.ts +53 -0
  1180. package/.forge/worktrees/pipeline-44a94121/lib/projects.ts +86 -0
  1181. package/.forge/worktrees/pipeline-44a94121/lib/session-manager.ts +156 -0
  1182. package/.forge/worktrees/pipeline-44a94121/lib/session-utils.ts +53 -0
  1183. package/.forge/worktrees/pipeline-44a94121/lib/session-watcher.ts +345 -0
  1184. package/.forge/worktrees/pipeline-44a94121/lib/settings.ts +195 -0
  1185. package/.forge/worktrees/pipeline-44a94121/lib/skills.ts +458 -0
  1186. package/.forge/worktrees/pipeline-44a94121/lib/task-manager.ts +949 -0
  1187. package/.forge/worktrees/pipeline-44a94121/lib/telegram-bot.ts +1477 -0
  1188. package/.forge/worktrees/pipeline-44a94121/lib/telegram-standalone.ts +83 -0
  1189. package/.forge/worktrees/pipeline-44a94121/lib/terminal-server.ts +70 -0
  1190. package/.forge/worktrees/pipeline-44a94121/lib/terminal-standalone.ts +421 -0
  1191. package/.forge/worktrees/pipeline-44a94121/lib/usage-scanner.ts +249 -0
  1192. package/.forge/worktrees/pipeline-44a94121/lib/workspace/__tests__/state-machine.test.ts +388 -0
  1193. package/.forge/worktrees/pipeline-44a94121/lib/workspace/__tests__/workspace.test.ts +311 -0
  1194. package/.forge/worktrees/pipeline-44a94121/lib/workspace/agent-bus.ts +416 -0
  1195. package/.forge/worktrees/pipeline-44a94121/lib/workspace/agent-worker.ts +655 -0
  1196. package/.forge/worktrees/pipeline-44a94121/lib/workspace/backends/api-backend.ts +262 -0
  1197. package/.forge/worktrees/pipeline-44a94121/lib/workspace/backends/cli-backend.ts +491 -0
  1198. package/.forge/worktrees/pipeline-44a94121/lib/workspace/index.ts +82 -0
  1199. package/.forge/worktrees/pipeline-44a94121/lib/workspace/manager.ts +136 -0
  1200. package/.forge/worktrees/pipeline-44a94121/lib/workspace/orchestrator.ts +3400 -0
  1201. package/.forge/worktrees/pipeline-44a94121/lib/workspace/persistence.ts +309 -0
  1202. package/.forge/worktrees/pipeline-44a94121/lib/workspace/presets.ts +649 -0
  1203. package/.forge/worktrees/pipeline-44a94121/lib/workspace/requests.ts +287 -0
  1204. package/.forge/worktrees/pipeline-44a94121/lib/workspace/session-monitor.ts +240 -0
  1205. package/.forge/worktrees/pipeline-44a94121/lib/workspace/skill-installer.ts +275 -0
  1206. package/.forge/worktrees/pipeline-44a94121/lib/workspace/smith-memory.ts +498 -0
  1207. package/.forge/worktrees/pipeline-44a94121/lib/workspace/types.ts +241 -0
  1208. package/.forge/worktrees/pipeline-44a94121/lib/workspace/watch-manager.ts +560 -0
  1209. package/.forge/worktrees/pipeline-44a94121/lib/workspace-standalone.ts +911 -0
  1210. package/.forge/worktrees/pipeline-44a94121/middleware.ts +51 -0
  1211. package/.forge/worktrees/pipeline-44a94121/next.config.ts +26 -0
  1212. package/.forge/worktrees/pipeline-44a94121/package.json +74 -0
  1213. package/.forge/worktrees/pipeline-44a94121/pnpm-lock.yaml +3719 -0
  1214. package/.forge/worktrees/pipeline-44a94121/pnpm-workspace.yaml +1 -0
  1215. package/.forge/worktrees/pipeline-44a94121/postcss.config.mjs +7 -0
  1216. package/.forge/worktrees/pipeline-44a94121/publish.sh +133 -0
  1217. package/.forge/worktrees/pipeline-44a94121/scripts/bench/README.md +66 -0
  1218. package/.forge/worktrees/pipeline-44a94121/scripts/bench/results/.gitignore +2 -0
  1219. package/.forge/worktrees/pipeline-44a94121/scripts/bench/run.ts +635 -0
  1220. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/01-text-utils/task.md +26 -0
  1221. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  1222. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  1223. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/02-pagination/task.md +48 -0
  1224. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  1225. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  1226. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  1227. package/.forge/worktrees/pipeline-44a94121/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  1228. package/.forge/worktrees/pipeline-44a94121/scripts/verify-usage.ts +178 -0
  1229. package/.forge/worktrees/pipeline-44a94121/src/config/index.ts +129 -0
  1230. package/.forge/worktrees/pipeline-44a94121/src/core/db/database.ts +259 -0
  1231. package/.forge/worktrees/pipeline-44a94121/src/core/memory/strategy.ts +32 -0
  1232. package/.forge/worktrees/pipeline-44a94121/src/core/providers/chat.ts +65 -0
  1233. package/.forge/worktrees/pipeline-44a94121/src/core/providers/registry.ts +60 -0
  1234. package/.forge/worktrees/pipeline-44a94121/src/core/session/manager.ts +190 -0
  1235. package/.forge/worktrees/pipeline-44a94121/src/types/index.ts +129 -0
  1236. package/.forge/worktrees/pipeline-44a94121/start.sh +31 -0
  1237. package/.forge/worktrees/pipeline-44a94121/templates/smith-lead.json +45 -0
  1238. package/.forge/worktrees/pipeline-44a94121/tsconfig.json +42 -0
  1239. package/.forge/worktrees/pipeline-4dd8dc2d/CLAUDE.md +86 -0
  1240. package/.forge/worktrees/pipeline-4dd8dc2d/README.md +136 -0
  1241. package/.forge/worktrees/pipeline-4dd8dc2d/RELEASE_NOTES.md +36 -0
  1242. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/agents/route.ts +17 -0
  1243. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/auth/[...nextauth]/route.ts +3 -0
  1244. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/auth/verify/route.ts +46 -0
  1245. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/[id]/route.ts +31 -0
  1246. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/[id]/stream/route.ts +63 -0
  1247. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/route.ts +28 -0
  1248. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  1249. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  1250. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/route.ts +37 -0
  1251. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/sync/route.ts +17 -0
  1252. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-templates/route.ts +145 -0
  1253. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/code/route.ts +299 -0
  1254. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/delivery/[id]/route.ts +62 -0
  1255. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/delivery/route.ts +40 -0
  1256. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/detect-cli/route.ts +46 -0
  1257. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/docs/route.ts +176 -0
  1258. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/docs/sessions/route.ts +54 -0
  1259. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/favorites/route.ts +26 -0
  1260. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/flows/route.ts +6 -0
  1261. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/flows/run/route.ts +19 -0
  1262. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/git/route.ts +149 -0
  1263. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/help/route.ts +84 -0
  1264. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/issue-scanner/route.ts +116 -0
  1265. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/logs/route.ts +100 -0
  1266. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/mobile-chat/route.ts +115 -0
  1267. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/monitor/route.ts +74 -0
  1268. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/notifications/route.ts +42 -0
  1269. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/notify/test/route.ts +33 -0
  1270. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/online/route.ts +40 -0
  1271. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/pipelines/[id]/route.ts +41 -0
  1272. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/pipelines/route.ts +90 -0
  1273. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/plugins/route.ts +75 -0
  1274. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/preview/[...path]/route.ts +64 -0
  1275. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/preview/route.ts +156 -0
  1276. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/project-pipelines/route.ts +91 -0
  1277. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/project-sessions/route.ts +61 -0
  1278. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/projects/route.ts +26 -0
  1279. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/chat/route.ts +64 -0
  1280. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/messages/route.ts +9 -0
  1281. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/route.ts +17 -0
  1282. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/route.ts +20 -0
  1283. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/settings/route.ts +64 -0
  1284. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/skills/local/route.ts +228 -0
  1285. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/skills/route.ts +182 -0
  1286. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/smith-templates/route.ts +81 -0
  1287. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/status/route.ts +12 -0
  1288. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tabs/route.ts +25 -0
  1289. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/[id]/route.ts +51 -0
  1290. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/[id]/stream/route.ts +77 -0
  1291. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/link/route.ts +37 -0
  1292. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/route.ts +44 -0
  1293. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/session/route.ts +14 -0
  1294. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/telegram/route.ts +23 -0
  1295. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/templates/route.ts +6 -0
  1296. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-bell/route.ts +39 -0
  1297. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-cwd/route.ts +19 -0
  1298. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-state/route.ts +15 -0
  1299. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tunnel/route.ts +26 -0
  1300. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/upgrade/route.ts +43 -0
  1301. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/usage/route.ts +20 -0
  1302. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/version/route.ts +78 -0
  1303. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/watchers/route.ts +33 -0
  1304. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/agents/route.ts +35 -0
  1305. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/memory/route.ts +23 -0
  1306. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/smith/route.ts +22 -0
  1307. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/stream/route.ts +31 -0
  1308. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/route.ts +79 -0
  1309. package/.forge/worktrees/pipeline-4dd8dc2d/app/global-error.tsx +21 -0
  1310. package/.forge/worktrees/pipeline-4dd8dc2d/app/globals.css +52 -0
  1311. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.ico +0 -0
  1312. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.png +0 -0
  1313. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.svg +106 -0
  1314. package/.forge/worktrees/pipeline-4dd8dc2d/app/layout.tsx +17 -0
  1315. package/.forge/worktrees/pipeline-4dd8dc2d/app/login/LoginForm.tsx +96 -0
  1316. package/.forge/worktrees/pipeline-4dd8dc2d/app/login/page.tsx +10 -0
  1317. package/.forge/worktrees/pipeline-4dd8dc2d/app/mobile/page.tsx +10 -0
  1318. package/.forge/worktrees/pipeline-4dd8dc2d/app/page.tsx +22 -0
  1319. package/.forge/worktrees/pipeline-4dd8dc2d/bin/forge-server.mjs +484 -0
  1320. package/.forge/worktrees/pipeline-4dd8dc2d/check-forge-status.sh +71 -0
  1321. package/.forge/worktrees/pipeline-4dd8dc2d/cli/mw.ts +579 -0
  1322. package/.forge/worktrees/pipeline-4dd8dc2d/components/BrowserPanel.tsx +175 -0
  1323. package/.forge/worktrees/pipeline-4dd8dc2d/components/ChatPanel.tsx +191 -0
  1324. package/.forge/worktrees/pipeline-4dd8dc2d/components/ClaudeTerminal.tsx +267 -0
  1325. package/.forge/worktrees/pipeline-4dd8dc2d/components/CodeViewer.tsx +787 -0
  1326. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationEditor.tsx +411 -0
  1327. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationGraphView.tsx +347 -0
  1328. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationTerminalView.tsx +303 -0
  1329. package/.forge/worktrees/pipeline-4dd8dc2d/components/Dashboard.tsx +807 -0
  1330. package/.forge/worktrees/pipeline-4dd8dc2d/components/DashboardWrapper.tsx +9 -0
  1331. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryFlowEditor.tsx +491 -0
  1332. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryList.tsx +230 -0
  1333. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryWorkspace.tsx +589 -0
  1334. package/.forge/worktrees/pipeline-4dd8dc2d/components/DocTerminal.tsx +187 -0
  1335. package/.forge/worktrees/pipeline-4dd8dc2d/components/DocsViewer.tsx +574 -0
  1336. package/.forge/worktrees/pipeline-4dd8dc2d/components/HelpDialog.tsx +169 -0
  1337. package/.forge/worktrees/pipeline-4dd8dc2d/components/HelpTerminal.tsx +141 -0
  1338. package/.forge/worktrees/pipeline-4dd8dc2d/components/InlinePipelineView.tsx +111 -0
  1339. package/.forge/worktrees/pipeline-4dd8dc2d/components/LogViewer.tsx +194 -0
  1340. package/.forge/worktrees/pipeline-4dd8dc2d/components/MarkdownContent.tsx +73 -0
  1341. package/.forge/worktrees/pipeline-4dd8dc2d/components/MobileView.tsx +385 -0
  1342. package/.forge/worktrees/pipeline-4dd8dc2d/components/MonitorPanel.tsx +122 -0
  1343. package/.forge/worktrees/pipeline-4dd8dc2d/components/NewSessionModal.tsx +93 -0
  1344. package/.forge/worktrees/pipeline-4dd8dc2d/components/NewTaskModal.tsx +492 -0
  1345. package/.forge/worktrees/pipeline-4dd8dc2d/components/PipelineEditor.tsx +570 -0
  1346. package/.forge/worktrees/pipeline-4dd8dc2d/components/PipelineView.tsx +1018 -0
  1347. package/.forge/worktrees/pipeline-4dd8dc2d/components/PluginsPanel.tsx +472 -0
  1348. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectDetail.tsx +1618 -0
  1349. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectList.tsx +108 -0
  1350. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectManager.tsx +401 -0
  1351. package/.forge/worktrees/pipeline-4dd8dc2d/components/SessionList.tsx +74 -0
  1352. package/.forge/worktrees/pipeline-4dd8dc2d/components/SessionView.tsx +726 -0
  1353. package/.forge/worktrees/pipeline-4dd8dc2d/components/SettingsModal.tsx +1647 -0
  1354. package/.forge/worktrees/pipeline-4dd8dc2d/components/SkillsPanel.tsx +969 -0
  1355. package/.forge/worktrees/pipeline-4dd8dc2d/components/StatusBar.tsx +99 -0
  1356. package/.forge/worktrees/pipeline-4dd8dc2d/components/TabBar.tsx +46 -0
  1357. package/.forge/worktrees/pipeline-4dd8dc2d/components/TaskBoard.tsx +113 -0
  1358. package/.forge/worktrees/pipeline-4dd8dc2d/components/TaskDetail.tsx +372 -0
  1359. package/.forge/worktrees/pipeline-4dd8dc2d/components/TerminalLauncher.tsx +398 -0
  1360. package/.forge/worktrees/pipeline-4dd8dc2d/components/TunnelToggle.tsx +206 -0
  1361. package/.forge/worktrees/pipeline-4dd8dc2d/components/UsagePanel.tsx +207 -0
  1362. package/.forge/worktrees/pipeline-4dd8dc2d/components/WebTerminal.tsx +1743 -0
  1363. package/.forge/worktrees/pipeline-4dd8dc2d/components/WorkspaceTree.tsx +221 -0
  1364. package/.forge/worktrees/pipeline-4dd8dc2d/components/WorkspaceView.tsx +4048 -0
  1365. package/.forge/worktrees/pipeline-4dd8dc2d/dev-test.sh +5 -0
  1366. package/.forge/worktrees/pipeline-4dd8dc2d/docs/Forge_Memory_Layer_Design.docx +0 -0
  1367. package/.forge/worktrees/pipeline-4dd8dc2d/docs/Forge_Strategy_Research_2026.docx +0 -0
  1368. package/.forge/worktrees/pipeline-4dd8dc2d/docs/LOCAL-DEPLOY.md +144 -0
  1369. package/.forge/worktrees/pipeline-4dd8dc2d/docs/roadmap-multi-agent-workflow.md +330 -0
  1370. package/.forge/worktrees/pipeline-4dd8dc2d/forge-logo.png +0 -0
  1371. package/.forge/worktrees/pipeline-4dd8dc2d/forge-logo.svg +106 -0
  1372. package/.forge/worktrees/pipeline-4dd8dc2d/hooks/useSidebarResize.ts +52 -0
  1373. package/.forge/worktrees/pipeline-4dd8dc2d/install.sh +29 -0
  1374. package/.forge/worktrees/pipeline-4dd8dc2d/instrumentation.ts +35 -0
  1375. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/claude-adapter.ts +104 -0
  1376. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/generic-adapter.ts +64 -0
  1377. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/index.ts +245 -0
  1378. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/types.ts +70 -0
  1379. package/.forge/worktrees/pipeline-4dd8dc2d/lib/artifacts.ts +106 -0
  1380. package/.forge/worktrees/pipeline-4dd8dc2d/lib/auth.ts +62 -0
  1381. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/docker.yaml +70 -0
  1382. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/http.yaml +66 -0
  1383. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/jenkins.yaml +92 -0
  1384. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/llm-vision.yaml +85 -0
  1385. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/playwright.yaml +111 -0
  1386. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/shell-command.yaml +60 -0
  1387. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/slack.yaml +48 -0
  1388. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/webhook.yaml +56 -0
  1389. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-process.ts +361 -0
  1390. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-sessions.ts +266 -0
  1391. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-templates.ts +227 -0
  1392. package/.forge/worktrees/pipeline-4dd8dc2d/lib/cloudflared.ts +424 -0
  1393. package/.forge/worktrees/pipeline-4dd8dc2d/lib/crypto.ts +67 -0
  1394. package/.forge/worktrees/pipeline-4dd8dc2d/lib/delivery.ts +787 -0
  1395. package/.forge/worktrees/pipeline-4dd8dc2d/lib/dirs.ts +99 -0
  1396. package/.forge/worktrees/pipeline-4dd8dc2d/lib/flows.ts +86 -0
  1397. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-mcp-server.ts +732 -0
  1398. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-inbox.md +38 -0
  1399. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-send.md +47 -0
  1400. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-status.md +32 -0
  1401. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-workspace-sync.md +37 -0
  1402. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/00-overview.md +40 -0
  1403. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/01-settings.md +194 -0
  1404. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/02-telegram.md +41 -0
  1405. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/03-tunnel.md +31 -0
  1406. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/04-tasks.md +52 -0
  1407. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/05-pipelines.md +460 -0
  1408. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/06-skills.md +43 -0
  1409. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/07-projects.md +73 -0
  1410. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/08-rules.md +53 -0
  1411. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/09-issue-autofix.md +55 -0
  1412. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/10-troubleshooting.md +89 -0
  1413. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/11-workspace.md +810 -0
  1414. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/CLAUDE.md +62 -0
  1415. package/.forge/worktrees/pipeline-4dd8dc2d/lib/init.ts +266 -0
  1416. package/.forge/worktrees/pipeline-4dd8dc2d/lib/issue-scanner.ts +298 -0
  1417. package/.forge/worktrees/pipeline-4dd8dc2d/lib/logger.ts +79 -0
  1418. package/.forge/worktrees/pipeline-4dd8dc2d/lib/notifications.ts +75 -0
  1419. package/.forge/worktrees/pipeline-4dd8dc2d/lib/notify.ts +108 -0
  1420. package/.forge/worktrees/pipeline-4dd8dc2d/lib/password.ts +97 -0
  1421. package/.forge/worktrees/pipeline-4dd8dc2d/lib/pipeline-scheduler.ts +373 -0
  1422. package/.forge/worktrees/pipeline-4dd8dc2d/lib/pipeline.ts +1565 -0
  1423. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/executor.ts +347 -0
  1424. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/registry.ts +228 -0
  1425. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/types.ts +103 -0
  1426. package/.forge/worktrees/pipeline-4dd8dc2d/lib/project-sessions.ts +53 -0
  1427. package/.forge/worktrees/pipeline-4dd8dc2d/lib/projects.ts +86 -0
  1428. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-manager.ts +156 -0
  1429. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-utils.ts +53 -0
  1430. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-watcher.ts +345 -0
  1431. package/.forge/worktrees/pipeline-4dd8dc2d/lib/settings.ts +195 -0
  1432. package/.forge/worktrees/pipeline-4dd8dc2d/lib/skills.ts +458 -0
  1433. package/.forge/worktrees/pipeline-4dd8dc2d/lib/task-manager.ts +951 -0
  1434. package/.forge/worktrees/pipeline-4dd8dc2d/lib/telegram-bot.ts +1477 -0
  1435. package/.forge/worktrees/pipeline-4dd8dc2d/lib/telegram-standalone.ts +83 -0
  1436. package/.forge/worktrees/pipeline-4dd8dc2d/lib/terminal-server.ts +70 -0
  1437. package/.forge/worktrees/pipeline-4dd8dc2d/lib/terminal-standalone.ts +438 -0
  1438. package/.forge/worktrees/pipeline-4dd8dc2d/lib/usage-scanner.ts +249 -0
  1439. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/__tests__/state-machine.test.ts +388 -0
  1440. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/__tests__/workspace.test.ts +311 -0
  1441. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/agent-bus.ts +416 -0
  1442. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/agent-worker.ts +655 -0
  1443. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/backends/api-backend.ts +262 -0
  1444. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/backends/cli-backend.ts +491 -0
  1445. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/index.ts +84 -0
  1446. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/manager.ts +136 -0
  1447. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/orchestrator.ts +3415 -0
  1448. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/persistence.ts +309 -0
  1449. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/presets.ts +649 -0
  1450. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/requests.ts +287 -0
  1451. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/session-monitor.ts +240 -0
  1452. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/skill-installer.ts +275 -0
  1453. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/smith-memory.ts +498 -0
  1454. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/types.ts +241 -0
  1455. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/watch-manager.ts +560 -0
  1456. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace-standalone.ts +978 -0
  1457. package/.forge/worktrees/pipeline-4dd8dc2d/middleware.ts +51 -0
  1458. package/.forge/worktrees/pipeline-4dd8dc2d/next.config.ts +26 -0
  1459. package/.forge/worktrees/pipeline-4dd8dc2d/package.json +74 -0
  1460. package/.forge/worktrees/pipeline-4dd8dc2d/pnpm-lock.yaml +3719 -0
  1461. package/.forge/worktrees/pipeline-4dd8dc2d/pnpm-workspace.yaml +1 -0
  1462. package/.forge/worktrees/pipeline-4dd8dc2d/postcss.config.mjs +7 -0
  1463. package/.forge/worktrees/pipeline-4dd8dc2d/publish.sh +133 -0
  1464. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/README.md +66 -0
  1465. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/results/.gitignore +2 -0
  1466. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/run.ts +635 -0
  1467. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/01-text-utils/task.md +26 -0
  1468. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  1469. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  1470. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/task.md +48 -0
  1471. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  1472. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  1473. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  1474. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  1475. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/verify-usage.ts +178 -0
  1476. package/.forge/worktrees/pipeline-4dd8dc2d/src/config/index.ts +129 -0
  1477. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/db/database.ts +259 -0
  1478. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/memory/strategy.ts +32 -0
  1479. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/providers/chat.ts +65 -0
  1480. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/providers/registry.ts +60 -0
  1481. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/session/manager.ts +190 -0
  1482. package/.forge/worktrees/pipeline-4dd8dc2d/src/types/index.ts +129 -0
  1483. package/.forge/worktrees/pipeline-4dd8dc2d/start.sh +32 -0
  1484. package/.forge/worktrees/pipeline-4dd8dc2d/templates/smith-lead.json +45 -0
  1485. package/.forge/worktrees/pipeline-4dd8dc2d/tsconfig.json +42 -0
  1486. package/.forge/worktrees/pipeline-d1757a50/CLAUDE.md +86 -0
  1487. package/.forge/worktrees/pipeline-d1757a50/README.md +136 -0
  1488. package/.forge/worktrees/pipeline-d1757a50/RELEASE_NOTES.md +11 -0
  1489. package/.forge/worktrees/pipeline-d1757a50/app/api/agents/route.ts +17 -0
  1490. package/.forge/worktrees/pipeline-d1757a50/app/api/auth/[...nextauth]/route.ts +3 -0
  1491. package/.forge/worktrees/pipeline-d1757a50/app/api/auth/verify/route.ts +46 -0
  1492. package/.forge/worktrees/pipeline-d1757a50/app/api/claude/[id]/route.ts +31 -0
  1493. package/.forge/worktrees/pipeline-d1757a50/app/api/claude/[id]/stream/route.ts +63 -0
  1494. package/.forge/worktrees/pipeline-d1757a50/app/api/claude/route.ts +28 -0
  1495. package/.forge/worktrees/pipeline-d1757a50/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  1496. package/.forge/worktrees/pipeline-d1757a50/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  1497. package/.forge/worktrees/pipeline-d1757a50/app/api/claude-sessions/[projectName]/route.ts +37 -0
  1498. package/.forge/worktrees/pipeline-d1757a50/app/api/claude-sessions/sync/route.ts +17 -0
  1499. package/.forge/worktrees/pipeline-d1757a50/app/api/claude-templates/route.ts +145 -0
  1500. package/.forge/worktrees/pipeline-d1757a50/app/api/code/route.ts +299 -0
  1501. package/.forge/worktrees/pipeline-d1757a50/app/api/delivery/[id]/route.ts +62 -0
  1502. package/.forge/worktrees/pipeline-d1757a50/app/api/delivery/route.ts +40 -0
  1503. package/.forge/worktrees/pipeline-d1757a50/app/api/detect-cli/route.ts +46 -0
  1504. package/.forge/worktrees/pipeline-d1757a50/app/api/docs/route.ts +176 -0
  1505. package/.forge/worktrees/pipeline-d1757a50/app/api/docs/sessions/route.ts +54 -0
  1506. package/.forge/worktrees/pipeline-d1757a50/app/api/favorites/route.ts +26 -0
  1507. package/.forge/worktrees/pipeline-d1757a50/app/api/flows/route.ts +6 -0
  1508. package/.forge/worktrees/pipeline-d1757a50/app/api/flows/run/route.ts +19 -0
  1509. package/.forge/worktrees/pipeline-d1757a50/app/api/git/route.ts +149 -0
  1510. package/.forge/worktrees/pipeline-d1757a50/app/api/help/route.ts +84 -0
  1511. package/.forge/worktrees/pipeline-d1757a50/app/api/issue-scanner/route.ts +116 -0
  1512. package/.forge/worktrees/pipeline-d1757a50/app/api/logs/route.ts +100 -0
  1513. package/.forge/worktrees/pipeline-d1757a50/app/api/mobile-chat/route.ts +115 -0
  1514. package/.forge/worktrees/pipeline-d1757a50/app/api/monitor/route.ts +74 -0
  1515. package/.forge/worktrees/pipeline-d1757a50/app/api/notifications/route.ts +42 -0
  1516. package/.forge/worktrees/pipeline-d1757a50/app/api/notify/test/route.ts +33 -0
  1517. package/.forge/worktrees/pipeline-d1757a50/app/api/online/route.ts +40 -0
  1518. package/.forge/worktrees/pipeline-d1757a50/app/api/pipelines/[id]/route.ts +41 -0
  1519. package/.forge/worktrees/pipeline-d1757a50/app/api/pipelines/route.ts +90 -0
  1520. package/.forge/worktrees/pipeline-d1757a50/app/api/plugins/route.ts +75 -0
  1521. package/.forge/worktrees/pipeline-d1757a50/app/api/preview/[...path]/route.ts +64 -0
  1522. package/.forge/worktrees/pipeline-d1757a50/app/api/preview/route.ts +156 -0
  1523. package/.forge/worktrees/pipeline-d1757a50/app/api/project-pipelines/route.ts +91 -0
  1524. package/.forge/worktrees/pipeline-d1757a50/app/api/project-sessions/route.ts +61 -0
  1525. package/.forge/worktrees/pipeline-d1757a50/app/api/projects/route.ts +26 -0
  1526. package/.forge/worktrees/pipeline-d1757a50/app/api/sessions/[id]/chat/route.ts +64 -0
  1527. package/.forge/worktrees/pipeline-d1757a50/app/api/sessions/[id]/messages/route.ts +9 -0
  1528. package/.forge/worktrees/pipeline-d1757a50/app/api/sessions/[id]/route.ts +17 -0
  1529. package/.forge/worktrees/pipeline-d1757a50/app/api/sessions/route.ts +20 -0
  1530. package/.forge/worktrees/pipeline-d1757a50/app/api/settings/route.ts +64 -0
  1531. package/.forge/worktrees/pipeline-d1757a50/app/api/skills/local/route.ts +228 -0
  1532. package/.forge/worktrees/pipeline-d1757a50/app/api/skills/route.ts +182 -0
  1533. package/.forge/worktrees/pipeline-d1757a50/app/api/smith-templates/route.ts +81 -0
  1534. package/.forge/worktrees/pipeline-d1757a50/app/api/status/route.ts +12 -0
  1535. package/.forge/worktrees/pipeline-d1757a50/app/api/tabs/route.ts +25 -0
  1536. package/.forge/worktrees/pipeline-d1757a50/app/api/tasks/[id]/route.ts +51 -0
  1537. package/.forge/worktrees/pipeline-d1757a50/app/api/tasks/[id]/stream/route.ts +77 -0
  1538. package/.forge/worktrees/pipeline-d1757a50/app/api/tasks/link/route.ts +37 -0
  1539. package/.forge/worktrees/pipeline-d1757a50/app/api/tasks/route.ts +44 -0
  1540. package/.forge/worktrees/pipeline-d1757a50/app/api/tasks/session/route.ts +14 -0
  1541. package/.forge/worktrees/pipeline-d1757a50/app/api/telegram/route.ts +23 -0
  1542. package/.forge/worktrees/pipeline-d1757a50/app/api/templates/route.ts +6 -0
  1543. package/.forge/worktrees/pipeline-d1757a50/app/api/terminal-bell/route.ts +35 -0
  1544. package/.forge/worktrees/pipeline-d1757a50/app/api/terminal-cwd/route.ts +19 -0
  1545. package/.forge/worktrees/pipeline-d1757a50/app/api/terminal-state/route.ts +15 -0
  1546. package/.forge/worktrees/pipeline-d1757a50/app/api/tunnel/route.ts +26 -0
  1547. package/.forge/worktrees/pipeline-d1757a50/app/api/upgrade/route.ts +43 -0
  1548. package/.forge/worktrees/pipeline-d1757a50/app/api/usage/route.ts +20 -0
  1549. package/.forge/worktrees/pipeline-d1757a50/app/api/version/route.ts +78 -0
  1550. package/.forge/worktrees/pipeline-d1757a50/app/api/watchers/route.ts +33 -0
  1551. package/.forge/worktrees/pipeline-d1757a50/app/api/workspace/[id]/agents/route.ts +35 -0
  1552. package/.forge/worktrees/pipeline-d1757a50/app/api/workspace/[id]/memory/route.ts +23 -0
  1553. package/.forge/worktrees/pipeline-d1757a50/app/api/workspace/[id]/smith/route.ts +22 -0
  1554. package/.forge/worktrees/pipeline-d1757a50/app/api/workspace/[id]/stream/route.ts +28 -0
  1555. package/.forge/worktrees/pipeline-d1757a50/app/api/workspace/route.ts +100 -0
  1556. package/.forge/worktrees/pipeline-d1757a50/app/global-error.tsx +21 -0
  1557. package/.forge/worktrees/pipeline-d1757a50/app/globals.css +52 -0
  1558. package/.forge/worktrees/pipeline-d1757a50/app/icon.ico +0 -0
  1559. package/.forge/worktrees/pipeline-d1757a50/app/icon.png +0 -0
  1560. package/.forge/worktrees/pipeline-d1757a50/app/icon.svg +106 -0
  1561. package/.forge/worktrees/pipeline-d1757a50/app/layout.tsx +17 -0
  1562. package/.forge/worktrees/pipeline-d1757a50/app/login/LoginForm.tsx +96 -0
  1563. package/.forge/worktrees/pipeline-d1757a50/app/login/page.tsx +10 -0
  1564. package/.forge/worktrees/pipeline-d1757a50/app/mobile/page.tsx +9 -0
  1565. package/.forge/worktrees/pipeline-d1757a50/app/page.tsx +21 -0
  1566. package/.forge/worktrees/pipeline-d1757a50/bin/forge-server.mjs +484 -0
  1567. package/.forge/worktrees/pipeline-d1757a50/check-forge-status.sh +71 -0
  1568. package/.forge/worktrees/pipeline-d1757a50/cli/mw.ts +579 -0
  1569. package/.forge/worktrees/pipeline-d1757a50/components/BrowserPanel.tsx +175 -0
  1570. package/.forge/worktrees/pipeline-d1757a50/components/ChatPanel.tsx +191 -0
  1571. package/.forge/worktrees/pipeline-d1757a50/components/ClaudeTerminal.tsx +267 -0
  1572. package/.forge/worktrees/pipeline-d1757a50/components/CodeViewer.tsx +787 -0
  1573. package/.forge/worktrees/pipeline-d1757a50/components/ConversationEditor.tsx +411 -0
  1574. package/.forge/worktrees/pipeline-d1757a50/components/ConversationGraphView.tsx +347 -0
  1575. package/.forge/worktrees/pipeline-d1757a50/components/ConversationTerminalView.tsx +303 -0
  1576. package/.forge/worktrees/pipeline-d1757a50/components/Dashboard.tsx +807 -0
  1577. package/.forge/worktrees/pipeline-d1757a50/components/DashboardWrapper.tsx +9 -0
  1578. package/.forge/worktrees/pipeline-d1757a50/components/DeliveryFlowEditor.tsx +491 -0
  1579. package/.forge/worktrees/pipeline-d1757a50/components/DeliveryList.tsx +230 -0
  1580. package/.forge/worktrees/pipeline-d1757a50/components/DeliveryWorkspace.tsx +589 -0
  1581. package/.forge/worktrees/pipeline-d1757a50/components/DocTerminal.tsx +187 -0
  1582. package/.forge/worktrees/pipeline-d1757a50/components/DocsViewer.tsx +574 -0
  1583. package/.forge/worktrees/pipeline-d1757a50/components/HelpDialog.tsx +169 -0
  1584. package/.forge/worktrees/pipeline-d1757a50/components/HelpTerminal.tsx +141 -0
  1585. package/.forge/worktrees/pipeline-d1757a50/components/InlinePipelineView.tsx +111 -0
  1586. package/.forge/worktrees/pipeline-d1757a50/components/LogViewer.tsx +194 -0
  1587. package/.forge/worktrees/pipeline-d1757a50/components/MarkdownContent.tsx +73 -0
  1588. package/.forge/worktrees/pipeline-d1757a50/components/MobileView.tsx +385 -0
  1589. package/.forge/worktrees/pipeline-d1757a50/components/MonitorPanel.tsx +122 -0
  1590. package/.forge/worktrees/pipeline-d1757a50/components/NewSessionModal.tsx +93 -0
  1591. package/.forge/worktrees/pipeline-d1757a50/components/NewTaskModal.tsx +492 -0
  1592. package/.forge/worktrees/pipeline-d1757a50/components/PipelineEditor.tsx +570 -0
  1593. package/.forge/worktrees/pipeline-d1757a50/components/PipelineView.tsx +1018 -0
  1594. package/.forge/worktrees/pipeline-d1757a50/components/PluginsPanel.tsx +472 -0
  1595. package/.forge/worktrees/pipeline-d1757a50/components/ProjectDetail.tsx +1618 -0
  1596. package/.forge/worktrees/pipeline-d1757a50/components/ProjectList.tsx +108 -0
  1597. package/.forge/worktrees/pipeline-d1757a50/components/ProjectManager.tsx +401 -0
  1598. package/.forge/worktrees/pipeline-d1757a50/components/SessionList.tsx +74 -0
  1599. package/.forge/worktrees/pipeline-d1757a50/components/SessionView.tsx +726 -0
  1600. package/.forge/worktrees/pipeline-d1757a50/components/SettingsModal.tsx +1647 -0
  1601. package/.forge/worktrees/pipeline-d1757a50/components/SkillsPanel.tsx +969 -0
  1602. package/.forge/worktrees/pipeline-d1757a50/components/StatusBar.tsx +99 -0
  1603. package/.forge/worktrees/pipeline-d1757a50/components/TabBar.tsx +46 -0
  1604. package/.forge/worktrees/pipeline-d1757a50/components/TaskBoard.tsx +113 -0
  1605. package/.forge/worktrees/pipeline-d1757a50/components/TaskDetail.tsx +372 -0
  1606. package/.forge/worktrees/pipeline-d1757a50/components/TerminalLauncher.tsx +398 -0
  1607. package/.forge/worktrees/pipeline-d1757a50/components/TunnelToggle.tsx +206 -0
  1608. package/.forge/worktrees/pipeline-d1757a50/components/UsagePanel.tsx +207 -0
  1609. package/.forge/worktrees/pipeline-d1757a50/components/WebTerminal.tsx +1683 -0
  1610. package/.forge/worktrees/pipeline-d1757a50/components/WorkspaceTree.tsx +221 -0
  1611. package/.forge/worktrees/pipeline-d1757a50/components/WorkspaceView.tsx +4048 -0
  1612. package/.forge/worktrees/pipeline-d1757a50/dev-test.sh +5 -0
  1613. package/.forge/worktrees/pipeline-d1757a50/docs/Forge_Memory_Layer_Design.docx +0 -0
  1614. package/.forge/worktrees/pipeline-d1757a50/docs/Forge_Strategy_Research_2026.docx +0 -0
  1615. package/.forge/worktrees/pipeline-d1757a50/docs/LOCAL-DEPLOY.md +144 -0
  1616. package/.forge/worktrees/pipeline-d1757a50/docs/roadmap-multi-agent-workflow.md +330 -0
  1617. package/.forge/worktrees/pipeline-d1757a50/forge-logo.png +0 -0
  1618. package/.forge/worktrees/pipeline-d1757a50/forge-logo.svg +106 -0
  1619. package/.forge/worktrees/pipeline-d1757a50/hooks/useSidebarResize.ts +52 -0
  1620. package/.forge/worktrees/pipeline-d1757a50/install.sh +29 -0
  1621. package/.forge/worktrees/pipeline-d1757a50/instrumentation.ts +35 -0
  1622. package/.forge/worktrees/pipeline-d1757a50/lib/agents/claude-adapter.ts +104 -0
  1623. package/.forge/worktrees/pipeline-d1757a50/lib/agents/generic-adapter.ts +64 -0
  1624. package/.forge/worktrees/pipeline-d1757a50/lib/agents/index.ts +245 -0
  1625. package/.forge/worktrees/pipeline-d1757a50/lib/agents/types.ts +70 -0
  1626. package/.forge/worktrees/pipeline-d1757a50/lib/artifacts.ts +106 -0
  1627. package/.forge/worktrees/pipeline-d1757a50/lib/auth.ts +62 -0
  1628. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/docker.yaml +70 -0
  1629. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/http.yaml +66 -0
  1630. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/jenkins.yaml +92 -0
  1631. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/llm-vision.yaml +85 -0
  1632. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/playwright.yaml +111 -0
  1633. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/shell-command.yaml +60 -0
  1634. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/slack.yaml +48 -0
  1635. package/.forge/worktrees/pipeline-d1757a50/lib/builtin-plugins/webhook.yaml +56 -0
  1636. package/.forge/worktrees/pipeline-d1757a50/lib/claude-process.ts +361 -0
  1637. package/.forge/worktrees/pipeline-d1757a50/lib/claude-sessions.ts +266 -0
  1638. package/.forge/worktrees/pipeline-d1757a50/lib/claude-templates.ts +227 -0
  1639. package/.forge/worktrees/pipeline-d1757a50/lib/cloudflared.ts +424 -0
  1640. package/.forge/worktrees/pipeline-d1757a50/lib/crypto.ts +67 -0
  1641. package/.forge/worktrees/pipeline-d1757a50/lib/delivery.ts +787 -0
  1642. package/.forge/worktrees/pipeline-d1757a50/lib/dirs.ts +99 -0
  1643. package/.forge/worktrees/pipeline-d1757a50/lib/flows.ts +86 -0
  1644. package/.forge/worktrees/pipeline-d1757a50/lib/forge-mcp-server.ts +717 -0
  1645. package/.forge/worktrees/pipeline-d1757a50/lib/forge-skills/forge-inbox.md +38 -0
  1646. package/.forge/worktrees/pipeline-d1757a50/lib/forge-skills/forge-send.md +47 -0
  1647. package/.forge/worktrees/pipeline-d1757a50/lib/forge-skills/forge-status.md +32 -0
  1648. package/.forge/worktrees/pipeline-d1757a50/lib/forge-skills/forge-workspace-sync.md +37 -0
  1649. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/00-overview.md +40 -0
  1650. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/01-settings.md +194 -0
  1651. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/02-telegram.md +41 -0
  1652. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/03-tunnel.md +31 -0
  1653. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/04-tasks.md +52 -0
  1654. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/05-pipelines.md +460 -0
  1655. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/06-skills.md +43 -0
  1656. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/07-projects.md +73 -0
  1657. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/08-rules.md +53 -0
  1658. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/09-issue-autofix.md +55 -0
  1659. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/10-troubleshooting.md +89 -0
  1660. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/11-workspace.md +810 -0
  1661. package/.forge/worktrees/pipeline-d1757a50/lib/help-docs/CLAUDE.md +62 -0
  1662. package/.forge/worktrees/pipeline-d1757a50/lib/init.ts +266 -0
  1663. package/.forge/worktrees/pipeline-d1757a50/lib/issue-scanner.ts +298 -0
  1664. package/.forge/worktrees/pipeline-d1757a50/lib/logger.ts +79 -0
  1665. package/.forge/worktrees/pipeline-d1757a50/lib/notifications.ts +75 -0
  1666. package/.forge/worktrees/pipeline-d1757a50/lib/notify.ts +108 -0
  1667. package/.forge/worktrees/pipeline-d1757a50/lib/password.ts +97 -0
  1668. package/.forge/worktrees/pipeline-d1757a50/lib/pipeline-scheduler.ts +373 -0
  1669. package/.forge/worktrees/pipeline-d1757a50/lib/pipeline.ts +1441 -0
  1670. package/.forge/worktrees/pipeline-d1757a50/lib/plugins/executor.ts +347 -0
  1671. package/.forge/worktrees/pipeline-d1757a50/lib/plugins/registry.ts +228 -0
  1672. package/.forge/worktrees/pipeline-d1757a50/lib/plugins/types.ts +103 -0
  1673. package/.forge/worktrees/pipeline-d1757a50/lib/project-sessions.ts +53 -0
  1674. package/.forge/worktrees/pipeline-d1757a50/lib/projects.ts +86 -0
  1675. package/.forge/worktrees/pipeline-d1757a50/lib/session-manager.ts +156 -0
  1676. package/.forge/worktrees/pipeline-d1757a50/lib/session-utils.ts +53 -0
  1677. package/.forge/worktrees/pipeline-d1757a50/lib/session-watcher.ts +345 -0
  1678. package/.forge/worktrees/pipeline-d1757a50/lib/settings.ts +195 -0
  1679. package/.forge/worktrees/pipeline-d1757a50/lib/skills.ts +458 -0
  1680. package/.forge/worktrees/pipeline-d1757a50/lib/task-manager.ts +949 -0
  1681. package/.forge/worktrees/pipeline-d1757a50/lib/telegram-bot.ts +1477 -0
  1682. package/.forge/worktrees/pipeline-d1757a50/lib/telegram-standalone.ts +83 -0
  1683. package/.forge/worktrees/pipeline-d1757a50/lib/terminal-server.ts +70 -0
  1684. package/.forge/worktrees/pipeline-d1757a50/lib/terminal-standalone.ts +421 -0
  1685. package/.forge/worktrees/pipeline-d1757a50/lib/usage-scanner.ts +249 -0
  1686. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/__tests__/state-machine.test.ts +388 -0
  1687. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/__tests__/workspace.test.ts +311 -0
  1688. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/agent-bus.ts +416 -0
  1689. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/agent-worker.ts +655 -0
  1690. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/backends/api-backend.ts +262 -0
  1691. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/backends/cli-backend.ts +491 -0
  1692. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/index.ts +82 -0
  1693. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/manager.ts +136 -0
  1694. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/orchestrator.ts +3400 -0
  1695. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/persistence.ts +309 -0
  1696. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/presets.ts +649 -0
  1697. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/requests.ts +287 -0
  1698. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/session-monitor.ts +240 -0
  1699. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/skill-installer.ts +275 -0
  1700. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/smith-memory.ts +498 -0
  1701. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/types.ts +241 -0
  1702. package/.forge/worktrees/pipeline-d1757a50/lib/workspace/watch-manager.ts +560 -0
  1703. package/.forge/worktrees/pipeline-d1757a50/lib/workspace-standalone.ts +911 -0
  1704. package/.forge/worktrees/pipeline-d1757a50/middleware.ts +51 -0
  1705. package/.forge/worktrees/pipeline-d1757a50/next.config.ts +26 -0
  1706. package/.forge/worktrees/pipeline-d1757a50/package.json +74 -0
  1707. package/.forge/worktrees/pipeline-d1757a50/pnpm-lock.yaml +3719 -0
  1708. package/.forge/worktrees/pipeline-d1757a50/pnpm-workspace.yaml +1 -0
  1709. package/.forge/worktrees/pipeline-d1757a50/postcss.config.mjs +7 -0
  1710. package/.forge/worktrees/pipeline-d1757a50/publish.sh +133 -0
  1711. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/README.md +66 -0
  1712. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/results/.gitignore +2 -0
  1713. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/run.ts +635 -0
  1714. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/01-text-utils/task.md +26 -0
  1715. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  1716. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  1717. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/02-pagination/task.md +48 -0
  1718. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  1719. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  1720. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  1721. package/.forge/worktrees/pipeline-d1757a50/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  1722. package/.forge/worktrees/pipeline-d1757a50/scripts/verify-usage.ts +178 -0
  1723. package/.forge/worktrees/pipeline-d1757a50/src/config/index.ts +129 -0
  1724. package/.forge/worktrees/pipeline-d1757a50/src/core/db/database.ts +259 -0
  1725. package/.forge/worktrees/pipeline-d1757a50/src/core/memory/strategy.ts +32 -0
  1726. package/.forge/worktrees/pipeline-d1757a50/src/core/providers/chat.ts +65 -0
  1727. package/.forge/worktrees/pipeline-d1757a50/src/core/providers/registry.ts +60 -0
  1728. package/.forge/worktrees/pipeline-d1757a50/src/core/session/manager.ts +190 -0
  1729. package/.forge/worktrees/pipeline-d1757a50/src/types/index.ts +129 -0
  1730. package/.forge/worktrees/pipeline-d1757a50/start.sh +31 -0
  1731. package/.forge/worktrees/pipeline-d1757a50/templates/smith-lead.json +45 -0
  1732. package/.forge/worktrees/pipeline-d1757a50/tsconfig.json +42 -0
  1733. package/.forge/worktrees/pipeline-d59c2fe2/CLAUDE.md +86 -0
  1734. package/.forge/worktrees/pipeline-d59c2fe2/README.md +136 -0
  1735. package/.forge/worktrees/pipeline-d59c2fe2/RELEASE_NOTES.md +11 -0
  1736. package/.forge/worktrees/pipeline-d59c2fe2/app/api/agents/route.ts +17 -0
  1737. package/.forge/worktrees/pipeline-d59c2fe2/app/api/auth/[...nextauth]/route.ts +3 -0
  1738. package/.forge/worktrees/pipeline-d59c2fe2/app/api/auth/verify/route.ts +46 -0
  1739. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude/[id]/route.ts +31 -0
  1740. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude/[id]/stream/route.ts +63 -0
  1741. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude/route.ts +28 -0
  1742. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  1743. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  1744. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude-sessions/[projectName]/route.ts +37 -0
  1745. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude-sessions/sync/route.ts +17 -0
  1746. package/.forge/worktrees/pipeline-d59c2fe2/app/api/claude-templates/route.ts +145 -0
  1747. package/.forge/worktrees/pipeline-d59c2fe2/app/api/code/route.ts +299 -0
  1748. package/.forge/worktrees/pipeline-d59c2fe2/app/api/delivery/[id]/route.ts +62 -0
  1749. package/.forge/worktrees/pipeline-d59c2fe2/app/api/delivery/route.ts +40 -0
  1750. package/.forge/worktrees/pipeline-d59c2fe2/app/api/detect-cli/route.ts +46 -0
  1751. package/.forge/worktrees/pipeline-d59c2fe2/app/api/docs/route.ts +176 -0
  1752. package/.forge/worktrees/pipeline-d59c2fe2/app/api/docs/sessions/route.ts +54 -0
  1753. package/.forge/worktrees/pipeline-d59c2fe2/app/api/favorites/route.ts +26 -0
  1754. package/.forge/worktrees/pipeline-d59c2fe2/app/api/flows/route.ts +6 -0
  1755. package/.forge/worktrees/pipeline-d59c2fe2/app/api/flows/run/route.ts +19 -0
  1756. package/.forge/worktrees/pipeline-d59c2fe2/app/api/git/route.ts +149 -0
  1757. package/.forge/worktrees/pipeline-d59c2fe2/app/api/help/route.ts +84 -0
  1758. package/.forge/worktrees/pipeline-d59c2fe2/app/api/issue-scanner/route.ts +116 -0
  1759. package/.forge/worktrees/pipeline-d59c2fe2/app/api/logs/route.ts +100 -0
  1760. package/.forge/worktrees/pipeline-d59c2fe2/app/api/mobile-chat/route.ts +115 -0
  1761. package/.forge/worktrees/pipeline-d59c2fe2/app/api/monitor/route.ts +74 -0
  1762. package/.forge/worktrees/pipeline-d59c2fe2/app/api/notifications/route.ts +42 -0
  1763. package/.forge/worktrees/pipeline-d59c2fe2/app/api/notify/test/route.ts +33 -0
  1764. package/.forge/worktrees/pipeline-d59c2fe2/app/api/online/route.ts +40 -0
  1765. package/.forge/worktrees/pipeline-d59c2fe2/app/api/pipelines/[id]/route.ts +41 -0
  1766. package/.forge/worktrees/pipeline-d59c2fe2/app/api/pipelines/route.ts +90 -0
  1767. package/.forge/worktrees/pipeline-d59c2fe2/app/api/plugins/route.ts +75 -0
  1768. package/.forge/worktrees/pipeline-d59c2fe2/app/api/preview/[...path]/route.ts +64 -0
  1769. package/.forge/worktrees/pipeline-d59c2fe2/app/api/preview/route.ts +156 -0
  1770. package/.forge/worktrees/pipeline-d59c2fe2/app/api/project-pipelines/route.ts +91 -0
  1771. package/.forge/worktrees/pipeline-d59c2fe2/app/api/project-sessions/route.ts +61 -0
  1772. package/.forge/worktrees/pipeline-d59c2fe2/app/api/projects/route.ts +26 -0
  1773. package/.forge/worktrees/pipeline-d59c2fe2/app/api/sessions/[id]/chat/route.ts +64 -0
  1774. package/.forge/worktrees/pipeline-d59c2fe2/app/api/sessions/[id]/messages/route.ts +9 -0
  1775. package/.forge/worktrees/pipeline-d59c2fe2/app/api/sessions/[id]/route.ts +17 -0
  1776. package/.forge/worktrees/pipeline-d59c2fe2/app/api/sessions/route.ts +20 -0
  1777. package/.forge/worktrees/pipeline-d59c2fe2/app/api/settings/route.ts +64 -0
  1778. package/.forge/worktrees/pipeline-d59c2fe2/app/api/skills/local/route.ts +228 -0
  1779. package/.forge/worktrees/pipeline-d59c2fe2/app/api/skills/route.ts +182 -0
  1780. package/.forge/worktrees/pipeline-d59c2fe2/app/api/smith-templates/route.ts +81 -0
  1781. package/.forge/worktrees/pipeline-d59c2fe2/app/api/status/route.ts +12 -0
  1782. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tabs/route.ts +25 -0
  1783. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tasks/[id]/route.ts +51 -0
  1784. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tasks/[id]/stream/route.ts +77 -0
  1785. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tasks/link/route.ts +37 -0
  1786. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tasks/route.ts +44 -0
  1787. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tasks/session/route.ts +14 -0
  1788. package/.forge/worktrees/pipeline-d59c2fe2/app/api/telegram/route.ts +23 -0
  1789. package/.forge/worktrees/pipeline-d59c2fe2/app/api/templates/route.ts +6 -0
  1790. package/.forge/worktrees/pipeline-d59c2fe2/app/api/terminal-bell/route.ts +35 -0
  1791. package/.forge/worktrees/pipeline-d59c2fe2/app/api/terminal-cwd/route.ts +19 -0
  1792. package/.forge/worktrees/pipeline-d59c2fe2/app/api/terminal-state/route.ts +15 -0
  1793. package/.forge/worktrees/pipeline-d59c2fe2/app/api/tunnel/route.ts +26 -0
  1794. package/.forge/worktrees/pipeline-d59c2fe2/app/api/upgrade/route.ts +43 -0
  1795. package/.forge/worktrees/pipeline-d59c2fe2/app/api/usage/route.ts +20 -0
  1796. package/.forge/worktrees/pipeline-d59c2fe2/app/api/version/route.ts +78 -0
  1797. package/.forge/worktrees/pipeline-d59c2fe2/app/api/watchers/route.ts +33 -0
  1798. package/.forge/worktrees/pipeline-d59c2fe2/app/api/workspace/[id]/agents/route.ts +35 -0
  1799. package/.forge/worktrees/pipeline-d59c2fe2/app/api/workspace/[id]/memory/route.ts +23 -0
  1800. package/.forge/worktrees/pipeline-d59c2fe2/app/api/workspace/[id]/smith/route.ts +22 -0
  1801. package/.forge/worktrees/pipeline-d59c2fe2/app/api/workspace/[id]/stream/route.ts +28 -0
  1802. package/.forge/worktrees/pipeline-d59c2fe2/app/api/workspace/route.ts +100 -0
  1803. package/.forge/worktrees/pipeline-d59c2fe2/app/global-error.tsx +21 -0
  1804. package/.forge/worktrees/pipeline-d59c2fe2/app/globals.css +52 -0
  1805. package/.forge/worktrees/pipeline-d59c2fe2/app/icon.ico +0 -0
  1806. package/.forge/worktrees/pipeline-d59c2fe2/app/icon.png +0 -0
  1807. package/.forge/worktrees/pipeline-d59c2fe2/app/icon.svg +106 -0
  1808. package/.forge/worktrees/pipeline-d59c2fe2/app/layout.tsx +17 -0
  1809. package/.forge/worktrees/pipeline-d59c2fe2/app/login/LoginForm.tsx +96 -0
  1810. package/.forge/worktrees/pipeline-d59c2fe2/app/login/page.tsx +10 -0
  1811. package/.forge/worktrees/pipeline-d59c2fe2/app/mobile/page.tsx +9 -0
  1812. package/.forge/worktrees/pipeline-d59c2fe2/app/page.tsx +21 -0
  1813. package/.forge/worktrees/pipeline-d59c2fe2/bin/forge-server.mjs +484 -0
  1814. package/.forge/worktrees/pipeline-d59c2fe2/check-forge-status.sh +71 -0
  1815. package/.forge/worktrees/pipeline-d59c2fe2/cli/mw.ts +579 -0
  1816. package/.forge/worktrees/pipeline-d59c2fe2/components/BrowserPanel.tsx +175 -0
  1817. package/.forge/worktrees/pipeline-d59c2fe2/components/ChatPanel.tsx +191 -0
  1818. package/.forge/worktrees/pipeline-d59c2fe2/components/ClaudeTerminal.tsx +267 -0
  1819. package/.forge/worktrees/pipeline-d59c2fe2/components/CodeViewer.tsx +787 -0
  1820. package/.forge/worktrees/pipeline-d59c2fe2/components/ConversationEditor.tsx +411 -0
  1821. package/.forge/worktrees/pipeline-d59c2fe2/components/ConversationGraphView.tsx +347 -0
  1822. package/.forge/worktrees/pipeline-d59c2fe2/components/ConversationTerminalView.tsx +303 -0
  1823. package/.forge/worktrees/pipeline-d59c2fe2/components/Dashboard.tsx +807 -0
  1824. package/.forge/worktrees/pipeline-d59c2fe2/components/DashboardWrapper.tsx +9 -0
  1825. package/.forge/worktrees/pipeline-d59c2fe2/components/DeliveryFlowEditor.tsx +491 -0
  1826. package/.forge/worktrees/pipeline-d59c2fe2/components/DeliveryList.tsx +230 -0
  1827. package/.forge/worktrees/pipeline-d59c2fe2/components/DeliveryWorkspace.tsx +589 -0
  1828. package/.forge/worktrees/pipeline-d59c2fe2/components/DocTerminal.tsx +187 -0
  1829. package/.forge/worktrees/pipeline-d59c2fe2/components/DocsViewer.tsx +574 -0
  1830. package/.forge/worktrees/pipeline-d59c2fe2/components/HelpDialog.tsx +169 -0
  1831. package/.forge/worktrees/pipeline-d59c2fe2/components/HelpTerminal.tsx +141 -0
  1832. package/.forge/worktrees/pipeline-d59c2fe2/components/InlinePipelineView.tsx +111 -0
  1833. package/.forge/worktrees/pipeline-d59c2fe2/components/LogViewer.tsx +194 -0
  1834. package/.forge/worktrees/pipeline-d59c2fe2/components/MarkdownContent.tsx +73 -0
  1835. package/.forge/worktrees/pipeline-d59c2fe2/components/MobileView.tsx +385 -0
  1836. package/.forge/worktrees/pipeline-d59c2fe2/components/MonitorPanel.tsx +122 -0
  1837. package/.forge/worktrees/pipeline-d59c2fe2/components/NewSessionModal.tsx +93 -0
  1838. package/.forge/worktrees/pipeline-d59c2fe2/components/NewTaskModal.tsx +492 -0
  1839. package/.forge/worktrees/pipeline-d59c2fe2/components/PipelineEditor.tsx +570 -0
  1840. package/.forge/worktrees/pipeline-d59c2fe2/components/PipelineView.tsx +1018 -0
  1841. package/.forge/worktrees/pipeline-d59c2fe2/components/PluginsPanel.tsx +472 -0
  1842. package/.forge/worktrees/pipeline-d59c2fe2/components/ProjectDetail.tsx +1618 -0
  1843. package/.forge/worktrees/pipeline-d59c2fe2/components/ProjectList.tsx +108 -0
  1844. package/.forge/worktrees/pipeline-d59c2fe2/components/ProjectManager.tsx +401 -0
  1845. package/.forge/worktrees/pipeline-d59c2fe2/components/SessionList.tsx +74 -0
  1846. package/.forge/worktrees/pipeline-d59c2fe2/components/SessionView.tsx +726 -0
  1847. package/.forge/worktrees/pipeline-d59c2fe2/components/SettingsModal.tsx +1647 -0
  1848. package/.forge/worktrees/pipeline-d59c2fe2/components/SkillsPanel.tsx +969 -0
  1849. package/.forge/worktrees/pipeline-d59c2fe2/components/StatusBar.tsx +99 -0
  1850. package/.forge/worktrees/pipeline-d59c2fe2/components/TabBar.tsx +46 -0
  1851. package/.forge/worktrees/pipeline-d59c2fe2/components/TaskBoard.tsx +113 -0
  1852. package/.forge/worktrees/pipeline-d59c2fe2/components/TaskDetail.tsx +372 -0
  1853. package/.forge/worktrees/pipeline-d59c2fe2/components/TerminalLauncher.tsx +398 -0
  1854. package/.forge/worktrees/pipeline-d59c2fe2/components/TunnelToggle.tsx +206 -0
  1855. package/.forge/worktrees/pipeline-d59c2fe2/components/UsagePanel.tsx +207 -0
  1856. package/.forge/worktrees/pipeline-d59c2fe2/components/WebTerminal.tsx +1683 -0
  1857. package/.forge/worktrees/pipeline-d59c2fe2/components/WorkspaceTree.tsx +221 -0
  1858. package/.forge/worktrees/pipeline-d59c2fe2/components/WorkspaceView.tsx +4048 -0
  1859. package/.forge/worktrees/pipeline-d59c2fe2/dev-test.sh +5 -0
  1860. package/.forge/worktrees/pipeline-d59c2fe2/docs/Forge_Memory_Layer_Design.docx +0 -0
  1861. package/.forge/worktrees/pipeline-d59c2fe2/docs/Forge_Strategy_Research_2026.docx +0 -0
  1862. package/.forge/worktrees/pipeline-d59c2fe2/docs/LOCAL-DEPLOY.md +144 -0
  1863. package/.forge/worktrees/pipeline-d59c2fe2/docs/roadmap-multi-agent-workflow.md +330 -0
  1864. package/.forge/worktrees/pipeline-d59c2fe2/forge-logo.png +0 -0
  1865. package/.forge/worktrees/pipeline-d59c2fe2/forge-logo.svg +106 -0
  1866. package/.forge/worktrees/pipeline-d59c2fe2/hooks/useSidebarResize.ts +52 -0
  1867. package/.forge/worktrees/pipeline-d59c2fe2/install.sh +29 -0
  1868. package/.forge/worktrees/pipeline-d59c2fe2/instrumentation.ts +35 -0
  1869. package/.forge/worktrees/pipeline-d59c2fe2/lib/agents/claude-adapter.ts +104 -0
  1870. package/.forge/worktrees/pipeline-d59c2fe2/lib/agents/generic-adapter.ts +64 -0
  1871. package/.forge/worktrees/pipeline-d59c2fe2/lib/agents/index.ts +245 -0
  1872. package/.forge/worktrees/pipeline-d59c2fe2/lib/agents/types.ts +70 -0
  1873. package/.forge/worktrees/pipeline-d59c2fe2/lib/artifacts.ts +106 -0
  1874. package/.forge/worktrees/pipeline-d59c2fe2/lib/auth.ts +62 -0
  1875. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/docker.yaml +70 -0
  1876. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/http.yaml +66 -0
  1877. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/jenkins.yaml +92 -0
  1878. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/llm-vision.yaml +85 -0
  1879. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/playwright.yaml +111 -0
  1880. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/shell-command.yaml +60 -0
  1881. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/slack.yaml +48 -0
  1882. package/.forge/worktrees/pipeline-d59c2fe2/lib/builtin-plugins/webhook.yaml +56 -0
  1883. package/.forge/worktrees/pipeline-d59c2fe2/lib/claude-process.ts +361 -0
  1884. package/.forge/worktrees/pipeline-d59c2fe2/lib/claude-sessions.ts +266 -0
  1885. package/.forge/worktrees/pipeline-d59c2fe2/lib/claude-templates.ts +227 -0
  1886. package/.forge/worktrees/pipeline-d59c2fe2/lib/cloudflared.ts +424 -0
  1887. package/.forge/worktrees/pipeline-d59c2fe2/lib/crypto.ts +67 -0
  1888. package/.forge/worktrees/pipeline-d59c2fe2/lib/delivery.ts +787 -0
  1889. package/.forge/worktrees/pipeline-d59c2fe2/lib/dirs.ts +99 -0
  1890. package/.forge/worktrees/pipeline-d59c2fe2/lib/flows.ts +86 -0
  1891. package/.forge/worktrees/pipeline-d59c2fe2/lib/forge-mcp-server.ts +717 -0
  1892. package/.forge/worktrees/pipeline-d59c2fe2/lib/forge-skills/forge-inbox.md +38 -0
  1893. package/.forge/worktrees/pipeline-d59c2fe2/lib/forge-skills/forge-send.md +47 -0
  1894. package/.forge/worktrees/pipeline-d59c2fe2/lib/forge-skills/forge-status.md +32 -0
  1895. package/.forge/worktrees/pipeline-d59c2fe2/lib/forge-skills/forge-workspace-sync.md +37 -0
  1896. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/00-overview.md +40 -0
  1897. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/01-settings.md +194 -0
  1898. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/02-telegram.md +41 -0
  1899. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/03-tunnel.md +31 -0
  1900. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/04-tasks.md +52 -0
  1901. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/05-pipelines.md +460 -0
  1902. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/06-skills.md +43 -0
  1903. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/07-projects.md +73 -0
  1904. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/08-rules.md +53 -0
  1905. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/09-issue-autofix.md +55 -0
  1906. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/10-troubleshooting.md +89 -0
  1907. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/11-workspace.md +810 -0
  1908. package/.forge/worktrees/pipeline-d59c2fe2/lib/help-docs/CLAUDE.md +62 -0
  1909. package/.forge/worktrees/pipeline-d59c2fe2/lib/init.ts +266 -0
  1910. package/.forge/worktrees/pipeline-d59c2fe2/lib/issue-scanner.ts +298 -0
  1911. package/.forge/worktrees/pipeline-d59c2fe2/lib/logger.ts +79 -0
  1912. package/.forge/worktrees/pipeline-d59c2fe2/lib/notifications.ts +75 -0
  1913. package/.forge/worktrees/pipeline-d59c2fe2/lib/notify.ts +108 -0
  1914. package/.forge/worktrees/pipeline-d59c2fe2/lib/password.ts +97 -0
  1915. package/.forge/worktrees/pipeline-d59c2fe2/lib/pipeline-scheduler.ts +373 -0
  1916. package/.forge/worktrees/pipeline-d59c2fe2/lib/pipeline.ts +1441 -0
  1917. package/.forge/worktrees/pipeline-d59c2fe2/lib/plugins/executor.ts +347 -0
  1918. package/.forge/worktrees/pipeline-d59c2fe2/lib/plugins/registry.ts +228 -0
  1919. package/.forge/worktrees/pipeline-d59c2fe2/lib/plugins/types.ts +103 -0
  1920. package/.forge/worktrees/pipeline-d59c2fe2/lib/project-sessions.ts +53 -0
  1921. package/.forge/worktrees/pipeline-d59c2fe2/lib/projects.ts +86 -0
  1922. package/.forge/worktrees/pipeline-d59c2fe2/lib/session-manager.ts +156 -0
  1923. package/.forge/worktrees/pipeline-d59c2fe2/lib/session-utils.ts +53 -0
  1924. package/.forge/worktrees/pipeline-d59c2fe2/lib/session-watcher.ts +345 -0
  1925. package/.forge/worktrees/pipeline-d59c2fe2/lib/settings.ts +195 -0
  1926. package/.forge/worktrees/pipeline-d59c2fe2/lib/skills.ts +458 -0
  1927. package/.forge/worktrees/pipeline-d59c2fe2/lib/task-manager.ts +949 -0
  1928. package/.forge/worktrees/pipeline-d59c2fe2/lib/telegram-bot.ts +1477 -0
  1929. package/.forge/worktrees/pipeline-d59c2fe2/lib/telegram-standalone.ts +83 -0
  1930. package/.forge/worktrees/pipeline-d59c2fe2/lib/terminal-server.ts +70 -0
  1931. package/.forge/worktrees/pipeline-d59c2fe2/lib/terminal-standalone.ts +421 -0
  1932. package/.forge/worktrees/pipeline-d59c2fe2/lib/usage-scanner.ts +249 -0
  1933. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/__tests__/state-machine.test.ts +388 -0
  1934. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/__tests__/workspace.test.ts +311 -0
  1935. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/agent-bus.ts +416 -0
  1936. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/agent-worker.ts +655 -0
  1937. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/backends/api-backend.ts +262 -0
  1938. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/backends/cli-backend.ts +491 -0
  1939. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/index.ts +82 -0
  1940. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/manager.ts +136 -0
  1941. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/orchestrator.ts +3400 -0
  1942. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/persistence.ts +309 -0
  1943. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/presets.ts +649 -0
  1944. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/requests.ts +287 -0
  1945. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/session-monitor.ts +240 -0
  1946. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/skill-installer.ts +275 -0
  1947. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/smith-memory.ts +498 -0
  1948. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/types.ts +241 -0
  1949. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace/watch-manager.ts +560 -0
  1950. package/.forge/worktrees/pipeline-d59c2fe2/lib/workspace-standalone.ts +911 -0
  1951. package/.forge/worktrees/pipeline-d59c2fe2/middleware.ts +51 -0
  1952. package/.forge/worktrees/pipeline-d59c2fe2/next.config.ts +26 -0
  1953. package/.forge/worktrees/pipeline-d59c2fe2/package.json +74 -0
  1954. package/.forge/worktrees/pipeline-d59c2fe2/pnpm-lock.yaml +3719 -0
  1955. package/.forge/worktrees/pipeline-d59c2fe2/pnpm-workspace.yaml +1 -0
  1956. package/.forge/worktrees/pipeline-d59c2fe2/postcss.config.mjs +7 -0
  1957. package/.forge/worktrees/pipeline-d59c2fe2/publish.sh +133 -0
  1958. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/README.md +66 -0
  1959. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/results/.gitignore +2 -0
  1960. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/run.ts +635 -0
  1961. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/01-text-utils/task.md +26 -0
  1962. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  1963. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  1964. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/02-pagination/task.md +48 -0
  1965. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  1966. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  1967. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  1968. package/.forge/worktrees/pipeline-d59c2fe2/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  1969. package/.forge/worktrees/pipeline-d59c2fe2/scripts/verify-usage.ts +178 -0
  1970. package/.forge/worktrees/pipeline-d59c2fe2/src/config/index.ts +129 -0
  1971. package/.forge/worktrees/pipeline-d59c2fe2/src/core/db/database.ts +259 -0
  1972. package/.forge/worktrees/pipeline-d59c2fe2/src/core/memory/strategy.ts +32 -0
  1973. package/.forge/worktrees/pipeline-d59c2fe2/src/core/providers/chat.ts +65 -0
  1974. package/.forge/worktrees/pipeline-d59c2fe2/src/core/providers/registry.ts +60 -0
  1975. package/.forge/worktrees/pipeline-d59c2fe2/src/core/session/manager.ts +190 -0
  1976. package/.forge/worktrees/pipeline-d59c2fe2/src/types/index.ts +129 -0
  1977. package/.forge/worktrees/pipeline-d59c2fe2/start.sh +31 -0
  1978. package/.forge/worktrees/pipeline-d59c2fe2/templates/smith-lead.json +45 -0
  1979. package/.forge/worktrees/pipeline-d59c2fe2/tsconfig.json +42 -0
  1980. package/.forge/worktrees/pipeline-d6a6ef23/CLAUDE.md +86 -0
  1981. package/.forge/worktrees/pipeline-d6a6ef23/README.md +136 -0
  1982. package/.forge/worktrees/pipeline-d6a6ef23/RELEASE_NOTES.md +11 -0
  1983. package/.forge/worktrees/pipeline-d6a6ef23/app/api/agents/route.ts +17 -0
  1984. package/.forge/worktrees/pipeline-d6a6ef23/app/api/auth/[...nextauth]/route.ts +3 -0
  1985. package/.forge/worktrees/pipeline-d6a6ef23/app/api/auth/verify/route.ts +46 -0
  1986. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude/[id]/route.ts +31 -0
  1987. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude/[id]/stream/route.ts +63 -0
  1988. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude/route.ts +28 -0
  1989. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  1990. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  1991. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude-sessions/[projectName]/route.ts +37 -0
  1992. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude-sessions/sync/route.ts +17 -0
  1993. package/.forge/worktrees/pipeline-d6a6ef23/app/api/claude-templates/route.ts +145 -0
  1994. package/.forge/worktrees/pipeline-d6a6ef23/app/api/code/route.ts +299 -0
  1995. package/.forge/worktrees/pipeline-d6a6ef23/app/api/delivery/[id]/route.ts +62 -0
  1996. package/.forge/worktrees/pipeline-d6a6ef23/app/api/delivery/route.ts +40 -0
  1997. package/.forge/worktrees/pipeline-d6a6ef23/app/api/detect-cli/route.ts +46 -0
  1998. package/.forge/worktrees/pipeline-d6a6ef23/app/api/docs/route.ts +176 -0
  1999. package/.forge/worktrees/pipeline-d6a6ef23/app/api/docs/sessions/route.ts +54 -0
  2000. package/.forge/worktrees/pipeline-d6a6ef23/app/api/favorites/route.ts +26 -0
  2001. package/.forge/worktrees/pipeline-d6a6ef23/app/api/flows/route.ts +6 -0
  2002. package/.forge/worktrees/pipeline-d6a6ef23/app/api/flows/run/route.ts +19 -0
  2003. package/.forge/worktrees/pipeline-d6a6ef23/app/api/git/route.ts +149 -0
  2004. package/.forge/worktrees/pipeline-d6a6ef23/app/api/help/route.ts +84 -0
  2005. package/.forge/worktrees/pipeline-d6a6ef23/app/api/issue-scanner/route.ts +116 -0
  2006. package/.forge/worktrees/pipeline-d6a6ef23/app/api/logs/route.ts +100 -0
  2007. package/.forge/worktrees/pipeline-d6a6ef23/app/api/mobile-chat/route.ts +115 -0
  2008. package/.forge/worktrees/pipeline-d6a6ef23/app/api/monitor/route.ts +74 -0
  2009. package/.forge/worktrees/pipeline-d6a6ef23/app/api/notifications/route.ts +42 -0
  2010. package/.forge/worktrees/pipeline-d6a6ef23/app/api/notify/test/route.ts +33 -0
  2011. package/.forge/worktrees/pipeline-d6a6ef23/app/api/online/route.ts +40 -0
  2012. package/.forge/worktrees/pipeline-d6a6ef23/app/api/pipelines/[id]/route.ts +41 -0
  2013. package/.forge/worktrees/pipeline-d6a6ef23/app/api/pipelines/route.ts +90 -0
  2014. package/.forge/worktrees/pipeline-d6a6ef23/app/api/plugins/route.ts +75 -0
  2015. package/.forge/worktrees/pipeline-d6a6ef23/app/api/preview/[...path]/route.ts +64 -0
  2016. package/.forge/worktrees/pipeline-d6a6ef23/app/api/preview/route.ts +156 -0
  2017. package/.forge/worktrees/pipeline-d6a6ef23/app/api/project-pipelines/route.ts +91 -0
  2018. package/.forge/worktrees/pipeline-d6a6ef23/app/api/project-sessions/route.ts +61 -0
  2019. package/.forge/worktrees/pipeline-d6a6ef23/app/api/projects/route.ts +26 -0
  2020. package/.forge/worktrees/pipeline-d6a6ef23/app/api/sessions/[id]/chat/route.ts +64 -0
  2021. package/.forge/worktrees/pipeline-d6a6ef23/app/api/sessions/[id]/messages/route.ts +9 -0
  2022. package/.forge/worktrees/pipeline-d6a6ef23/app/api/sessions/[id]/route.ts +17 -0
  2023. package/.forge/worktrees/pipeline-d6a6ef23/app/api/sessions/route.ts +20 -0
  2024. package/.forge/worktrees/pipeline-d6a6ef23/app/api/settings/route.ts +64 -0
  2025. package/.forge/worktrees/pipeline-d6a6ef23/app/api/skills/local/route.ts +228 -0
  2026. package/.forge/worktrees/pipeline-d6a6ef23/app/api/skills/route.ts +182 -0
  2027. package/.forge/worktrees/pipeline-d6a6ef23/app/api/smith-templates/route.ts +81 -0
  2028. package/.forge/worktrees/pipeline-d6a6ef23/app/api/status/route.ts +12 -0
  2029. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tabs/route.ts +25 -0
  2030. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tasks/[id]/route.ts +51 -0
  2031. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tasks/[id]/stream/route.ts +77 -0
  2032. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tasks/link/route.ts +37 -0
  2033. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tasks/route.ts +44 -0
  2034. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tasks/session/route.ts +14 -0
  2035. package/.forge/worktrees/pipeline-d6a6ef23/app/api/telegram/route.ts +23 -0
  2036. package/.forge/worktrees/pipeline-d6a6ef23/app/api/templates/route.ts +6 -0
  2037. package/.forge/worktrees/pipeline-d6a6ef23/app/api/terminal-bell/route.ts +35 -0
  2038. package/.forge/worktrees/pipeline-d6a6ef23/app/api/terminal-cwd/route.ts +19 -0
  2039. package/.forge/worktrees/pipeline-d6a6ef23/app/api/terminal-state/route.ts +15 -0
  2040. package/.forge/worktrees/pipeline-d6a6ef23/app/api/tunnel/route.ts +26 -0
  2041. package/.forge/worktrees/pipeline-d6a6ef23/app/api/upgrade/route.ts +43 -0
  2042. package/.forge/worktrees/pipeline-d6a6ef23/app/api/usage/route.ts +20 -0
  2043. package/.forge/worktrees/pipeline-d6a6ef23/app/api/version/route.ts +78 -0
  2044. package/.forge/worktrees/pipeline-d6a6ef23/app/api/watchers/route.ts +33 -0
  2045. package/.forge/worktrees/pipeline-d6a6ef23/app/api/workspace/[id]/agents/route.ts +35 -0
  2046. package/.forge/worktrees/pipeline-d6a6ef23/app/api/workspace/[id]/memory/route.ts +23 -0
  2047. package/.forge/worktrees/pipeline-d6a6ef23/app/api/workspace/[id]/smith/route.ts +22 -0
  2048. package/.forge/worktrees/pipeline-d6a6ef23/app/api/workspace/[id]/stream/route.ts +28 -0
  2049. package/.forge/worktrees/pipeline-d6a6ef23/app/api/workspace/route.ts +100 -0
  2050. package/.forge/worktrees/pipeline-d6a6ef23/app/global-error.tsx +21 -0
  2051. package/.forge/worktrees/pipeline-d6a6ef23/app/globals.css +52 -0
  2052. package/.forge/worktrees/pipeline-d6a6ef23/app/icon.ico +0 -0
  2053. package/.forge/worktrees/pipeline-d6a6ef23/app/icon.png +0 -0
  2054. package/.forge/worktrees/pipeline-d6a6ef23/app/icon.svg +106 -0
  2055. package/.forge/worktrees/pipeline-d6a6ef23/app/layout.tsx +17 -0
  2056. package/.forge/worktrees/pipeline-d6a6ef23/app/login/LoginForm.tsx +96 -0
  2057. package/.forge/worktrees/pipeline-d6a6ef23/app/login/page.tsx +10 -0
  2058. package/.forge/worktrees/pipeline-d6a6ef23/app/mobile/page.tsx +9 -0
  2059. package/.forge/worktrees/pipeline-d6a6ef23/app/page.tsx +21 -0
  2060. package/.forge/worktrees/pipeline-d6a6ef23/bin/forge-server.mjs +484 -0
  2061. package/.forge/worktrees/pipeline-d6a6ef23/check-forge-status.sh +71 -0
  2062. package/.forge/worktrees/pipeline-d6a6ef23/cli/mw.ts +579 -0
  2063. package/.forge/worktrees/pipeline-d6a6ef23/components/BrowserPanel.tsx +175 -0
  2064. package/.forge/worktrees/pipeline-d6a6ef23/components/ChatPanel.tsx +191 -0
  2065. package/.forge/worktrees/pipeline-d6a6ef23/components/ClaudeTerminal.tsx +267 -0
  2066. package/.forge/worktrees/pipeline-d6a6ef23/components/CodeViewer.tsx +787 -0
  2067. package/.forge/worktrees/pipeline-d6a6ef23/components/ConversationEditor.tsx +411 -0
  2068. package/.forge/worktrees/pipeline-d6a6ef23/components/ConversationGraphView.tsx +347 -0
  2069. package/.forge/worktrees/pipeline-d6a6ef23/components/ConversationTerminalView.tsx +303 -0
  2070. package/.forge/worktrees/pipeline-d6a6ef23/components/Dashboard.tsx +807 -0
  2071. package/.forge/worktrees/pipeline-d6a6ef23/components/DashboardWrapper.tsx +9 -0
  2072. package/.forge/worktrees/pipeline-d6a6ef23/components/DeliveryFlowEditor.tsx +491 -0
  2073. package/.forge/worktrees/pipeline-d6a6ef23/components/DeliveryList.tsx +230 -0
  2074. package/.forge/worktrees/pipeline-d6a6ef23/components/DeliveryWorkspace.tsx +589 -0
  2075. package/.forge/worktrees/pipeline-d6a6ef23/components/DocTerminal.tsx +187 -0
  2076. package/.forge/worktrees/pipeline-d6a6ef23/components/DocsViewer.tsx +574 -0
  2077. package/.forge/worktrees/pipeline-d6a6ef23/components/HelpDialog.tsx +169 -0
  2078. package/.forge/worktrees/pipeline-d6a6ef23/components/HelpTerminal.tsx +141 -0
  2079. package/.forge/worktrees/pipeline-d6a6ef23/components/InlinePipelineView.tsx +111 -0
  2080. package/.forge/worktrees/pipeline-d6a6ef23/components/LogViewer.tsx +194 -0
  2081. package/.forge/worktrees/pipeline-d6a6ef23/components/MarkdownContent.tsx +73 -0
  2082. package/.forge/worktrees/pipeline-d6a6ef23/components/MobileView.tsx +385 -0
  2083. package/.forge/worktrees/pipeline-d6a6ef23/components/MonitorPanel.tsx +122 -0
  2084. package/.forge/worktrees/pipeline-d6a6ef23/components/NewSessionModal.tsx +93 -0
  2085. package/.forge/worktrees/pipeline-d6a6ef23/components/NewTaskModal.tsx +492 -0
  2086. package/.forge/worktrees/pipeline-d6a6ef23/components/PipelineEditor.tsx +570 -0
  2087. package/.forge/worktrees/pipeline-d6a6ef23/components/PipelineView.tsx +1018 -0
  2088. package/.forge/worktrees/pipeline-d6a6ef23/components/PluginsPanel.tsx +472 -0
  2089. package/.forge/worktrees/pipeline-d6a6ef23/components/ProjectDetail.tsx +1618 -0
  2090. package/.forge/worktrees/pipeline-d6a6ef23/components/ProjectList.tsx +108 -0
  2091. package/.forge/worktrees/pipeline-d6a6ef23/components/ProjectManager.tsx +401 -0
  2092. package/.forge/worktrees/pipeline-d6a6ef23/components/SessionList.tsx +74 -0
  2093. package/.forge/worktrees/pipeline-d6a6ef23/components/SessionView.tsx +726 -0
  2094. package/.forge/worktrees/pipeline-d6a6ef23/components/SettingsModal.tsx +1647 -0
  2095. package/.forge/worktrees/pipeline-d6a6ef23/components/SkillsPanel.tsx +969 -0
  2096. package/.forge/worktrees/pipeline-d6a6ef23/components/StatusBar.tsx +99 -0
  2097. package/.forge/worktrees/pipeline-d6a6ef23/components/TabBar.tsx +46 -0
  2098. package/.forge/worktrees/pipeline-d6a6ef23/components/TaskBoard.tsx +113 -0
  2099. package/.forge/worktrees/pipeline-d6a6ef23/components/TaskDetail.tsx +372 -0
  2100. package/.forge/worktrees/pipeline-d6a6ef23/components/TerminalLauncher.tsx +398 -0
  2101. package/.forge/worktrees/pipeline-d6a6ef23/components/TunnelToggle.tsx +206 -0
  2102. package/.forge/worktrees/pipeline-d6a6ef23/components/UsagePanel.tsx +207 -0
  2103. package/.forge/worktrees/pipeline-d6a6ef23/components/WebTerminal.tsx +1683 -0
  2104. package/.forge/worktrees/pipeline-d6a6ef23/components/WorkspaceTree.tsx +221 -0
  2105. package/.forge/worktrees/pipeline-d6a6ef23/components/WorkspaceView.tsx +4048 -0
  2106. package/.forge/worktrees/pipeline-d6a6ef23/dev-test.sh +5 -0
  2107. package/.forge/worktrees/pipeline-d6a6ef23/docs/Forge_Memory_Layer_Design.docx +0 -0
  2108. package/.forge/worktrees/pipeline-d6a6ef23/docs/Forge_Strategy_Research_2026.docx +0 -0
  2109. package/.forge/worktrees/pipeline-d6a6ef23/docs/LOCAL-DEPLOY.md +144 -0
  2110. package/.forge/worktrees/pipeline-d6a6ef23/docs/roadmap-multi-agent-workflow.md +330 -0
  2111. package/.forge/worktrees/pipeline-d6a6ef23/forge-logo.png +0 -0
  2112. package/.forge/worktrees/pipeline-d6a6ef23/forge-logo.svg +106 -0
  2113. package/.forge/worktrees/pipeline-d6a6ef23/hooks/useSidebarResize.ts +52 -0
  2114. package/.forge/worktrees/pipeline-d6a6ef23/install.sh +29 -0
  2115. package/.forge/worktrees/pipeline-d6a6ef23/instrumentation.ts +35 -0
  2116. package/.forge/worktrees/pipeline-d6a6ef23/lib/agents/claude-adapter.ts +104 -0
  2117. package/.forge/worktrees/pipeline-d6a6ef23/lib/agents/generic-adapter.ts +64 -0
  2118. package/.forge/worktrees/pipeline-d6a6ef23/lib/agents/index.ts +245 -0
  2119. package/.forge/worktrees/pipeline-d6a6ef23/lib/agents/types.ts +70 -0
  2120. package/.forge/worktrees/pipeline-d6a6ef23/lib/artifacts.ts +106 -0
  2121. package/.forge/worktrees/pipeline-d6a6ef23/lib/auth.ts +62 -0
  2122. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/docker.yaml +70 -0
  2123. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/http.yaml +66 -0
  2124. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/jenkins.yaml +92 -0
  2125. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/llm-vision.yaml +85 -0
  2126. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/playwright.yaml +111 -0
  2127. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/shell-command.yaml +60 -0
  2128. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/slack.yaml +48 -0
  2129. package/.forge/worktrees/pipeline-d6a6ef23/lib/builtin-plugins/webhook.yaml +56 -0
  2130. package/.forge/worktrees/pipeline-d6a6ef23/lib/claude-process.ts +352 -0
  2131. package/.forge/worktrees/pipeline-d6a6ef23/lib/claude-sessions.ts +266 -0
  2132. package/.forge/worktrees/pipeline-d6a6ef23/lib/claude-templates.ts +227 -0
  2133. package/.forge/worktrees/pipeline-d6a6ef23/lib/cloudflared.ts +424 -0
  2134. package/.forge/worktrees/pipeline-d6a6ef23/lib/crypto.ts +67 -0
  2135. package/.forge/worktrees/pipeline-d6a6ef23/lib/delivery.ts +787 -0
  2136. package/.forge/worktrees/pipeline-d6a6ef23/lib/dirs.ts +99 -0
  2137. package/.forge/worktrees/pipeline-d6a6ef23/lib/flows.ts +86 -0
  2138. package/.forge/worktrees/pipeline-d6a6ef23/lib/forge-mcp-server.ts +717 -0
  2139. package/.forge/worktrees/pipeline-d6a6ef23/lib/forge-skills/forge-inbox.md +38 -0
  2140. package/.forge/worktrees/pipeline-d6a6ef23/lib/forge-skills/forge-send.md +47 -0
  2141. package/.forge/worktrees/pipeline-d6a6ef23/lib/forge-skills/forge-status.md +32 -0
  2142. package/.forge/worktrees/pipeline-d6a6ef23/lib/forge-skills/forge-workspace-sync.md +37 -0
  2143. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/00-overview.md +40 -0
  2144. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/01-settings.md +194 -0
  2145. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/02-telegram.md +41 -0
  2146. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/03-tunnel.md +31 -0
  2147. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/04-tasks.md +52 -0
  2148. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/05-pipelines.md +460 -0
  2149. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/06-skills.md +43 -0
  2150. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/07-projects.md +73 -0
  2151. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/08-rules.md +53 -0
  2152. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/09-issue-autofix.md +55 -0
  2153. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/10-troubleshooting.md +89 -0
  2154. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/11-workspace.md +810 -0
  2155. package/.forge/worktrees/pipeline-d6a6ef23/lib/help-docs/CLAUDE.md +62 -0
  2156. package/.forge/worktrees/pipeline-d6a6ef23/lib/init.ts +266 -0
  2157. package/.forge/worktrees/pipeline-d6a6ef23/lib/issue-scanner.ts +298 -0
  2158. package/.forge/worktrees/pipeline-d6a6ef23/lib/logger.ts +79 -0
  2159. package/.forge/worktrees/pipeline-d6a6ef23/lib/notifications.ts +75 -0
  2160. package/.forge/worktrees/pipeline-d6a6ef23/lib/notify.ts +108 -0
  2161. package/.forge/worktrees/pipeline-d6a6ef23/lib/password.ts +97 -0
  2162. package/.forge/worktrees/pipeline-d6a6ef23/lib/pipeline-scheduler.ts +373 -0
  2163. package/.forge/worktrees/pipeline-d6a6ef23/lib/pipeline.ts +1438 -0
  2164. package/.forge/worktrees/pipeline-d6a6ef23/lib/plugins/executor.ts +347 -0
  2165. package/.forge/worktrees/pipeline-d6a6ef23/lib/plugins/registry.ts +228 -0
  2166. package/.forge/worktrees/pipeline-d6a6ef23/lib/plugins/types.ts +103 -0
  2167. package/.forge/worktrees/pipeline-d6a6ef23/lib/project-sessions.ts +53 -0
  2168. package/.forge/worktrees/pipeline-d6a6ef23/lib/projects.ts +86 -0
  2169. package/.forge/worktrees/pipeline-d6a6ef23/lib/session-manager.ts +156 -0
  2170. package/.forge/worktrees/pipeline-d6a6ef23/lib/session-utils.ts +53 -0
  2171. package/.forge/worktrees/pipeline-d6a6ef23/lib/session-watcher.ts +345 -0
  2172. package/.forge/worktrees/pipeline-d6a6ef23/lib/settings.ts +195 -0
  2173. package/.forge/worktrees/pipeline-d6a6ef23/lib/skills.ts +458 -0
  2174. package/.forge/worktrees/pipeline-d6a6ef23/lib/task-manager.ts +949 -0
  2175. package/.forge/worktrees/pipeline-d6a6ef23/lib/telegram-bot.ts +1477 -0
  2176. package/.forge/worktrees/pipeline-d6a6ef23/lib/telegram-standalone.ts +83 -0
  2177. package/.forge/worktrees/pipeline-d6a6ef23/lib/terminal-server.ts +70 -0
  2178. package/.forge/worktrees/pipeline-d6a6ef23/lib/terminal-standalone.ts +421 -0
  2179. package/.forge/worktrees/pipeline-d6a6ef23/lib/usage-scanner.ts +249 -0
  2180. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/__tests__/state-machine.test.ts +388 -0
  2181. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/__tests__/workspace.test.ts +311 -0
  2182. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/agent-bus.ts +416 -0
  2183. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/agent-worker.ts +655 -0
  2184. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/backends/api-backend.ts +262 -0
  2185. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/backends/cli-backend.ts +491 -0
  2186. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/index.ts +82 -0
  2187. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/manager.ts +136 -0
  2188. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/orchestrator.ts +3400 -0
  2189. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/persistence.ts +309 -0
  2190. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/presets.ts +649 -0
  2191. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/requests.ts +287 -0
  2192. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/session-monitor.ts +240 -0
  2193. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/skill-installer.ts +275 -0
  2194. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/smith-memory.ts +498 -0
  2195. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/types.ts +241 -0
  2196. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace/watch-manager.ts +560 -0
  2197. package/.forge/worktrees/pipeline-d6a6ef23/lib/workspace-standalone.ts +911 -0
  2198. package/.forge/worktrees/pipeline-d6a6ef23/middleware.ts +51 -0
  2199. package/.forge/worktrees/pipeline-d6a6ef23/next.config.ts +26 -0
  2200. package/.forge/worktrees/pipeline-d6a6ef23/package.json +74 -0
  2201. package/.forge/worktrees/pipeline-d6a6ef23/pnpm-lock.yaml +3719 -0
  2202. package/.forge/worktrees/pipeline-d6a6ef23/pnpm-workspace.yaml +1 -0
  2203. package/.forge/worktrees/pipeline-d6a6ef23/postcss.config.mjs +7 -0
  2204. package/.forge/worktrees/pipeline-d6a6ef23/publish.sh +133 -0
  2205. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/README.md +66 -0
  2206. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/results/.gitignore +2 -0
  2207. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/run.ts +635 -0
  2208. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/01-text-utils/task.md +26 -0
  2209. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  2210. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  2211. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/02-pagination/task.md +48 -0
  2212. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  2213. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  2214. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  2215. package/.forge/worktrees/pipeline-d6a6ef23/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  2216. package/.forge/worktrees/pipeline-d6a6ef23/scripts/verify-usage.ts +178 -0
  2217. package/.forge/worktrees/pipeline-d6a6ef23/src/config/index.ts +129 -0
  2218. package/.forge/worktrees/pipeline-d6a6ef23/src/core/db/database.ts +259 -0
  2219. package/.forge/worktrees/pipeline-d6a6ef23/src/core/memory/strategy.ts +32 -0
  2220. package/.forge/worktrees/pipeline-d6a6ef23/src/core/providers/chat.ts +65 -0
  2221. package/.forge/worktrees/pipeline-d6a6ef23/src/core/providers/registry.ts +60 -0
  2222. package/.forge/worktrees/pipeline-d6a6ef23/src/core/session/manager.ts +190 -0
  2223. package/.forge/worktrees/pipeline-d6a6ef23/src/types/index.ts +129 -0
  2224. package/.forge/worktrees/pipeline-d6a6ef23/start.sh +31 -0
  2225. package/.forge/worktrees/pipeline-d6a6ef23/templates/smith-lead.json +45 -0
  2226. package/.forge/worktrees/pipeline-d6a6ef23/tsconfig.json +42 -0
  2227. package/.forge/worktrees/pipeline-e7f78b7a/CLAUDE.md +86 -0
  2228. package/.forge/worktrees/pipeline-e7f78b7a/README.md +136 -0
  2229. package/.forge/worktrees/pipeline-e7f78b7a/RELEASE_NOTES.md +11 -0
  2230. package/.forge/worktrees/pipeline-e7f78b7a/app/api/agents/route.ts +17 -0
  2231. package/.forge/worktrees/pipeline-e7f78b7a/app/api/auth/[...nextauth]/route.ts +3 -0
  2232. package/.forge/worktrees/pipeline-e7f78b7a/app/api/auth/verify/route.ts +46 -0
  2233. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude/[id]/route.ts +31 -0
  2234. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude/[id]/stream/route.ts +63 -0
  2235. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude/route.ts +28 -0
  2236. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  2237. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  2238. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude-sessions/[projectName]/route.ts +37 -0
  2239. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude-sessions/sync/route.ts +17 -0
  2240. package/.forge/worktrees/pipeline-e7f78b7a/app/api/claude-templates/route.ts +145 -0
  2241. package/.forge/worktrees/pipeline-e7f78b7a/app/api/code/route.ts +299 -0
  2242. package/.forge/worktrees/pipeline-e7f78b7a/app/api/delivery/[id]/route.ts +62 -0
  2243. package/.forge/worktrees/pipeline-e7f78b7a/app/api/delivery/route.ts +40 -0
  2244. package/.forge/worktrees/pipeline-e7f78b7a/app/api/detect-cli/route.ts +46 -0
  2245. package/.forge/worktrees/pipeline-e7f78b7a/app/api/docs/route.ts +176 -0
  2246. package/.forge/worktrees/pipeline-e7f78b7a/app/api/docs/sessions/route.ts +54 -0
  2247. package/.forge/worktrees/pipeline-e7f78b7a/app/api/favorites/route.ts +26 -0
  2248. package/.forge/worktrees/pipeline-e7f78b7a/app/api/flows/route.ts +6 -0
  2249. package/.forge/worktrees/pipeline-e7f78b7a/app/api/flows/run/route.ts +19 -0
  2250. package/.forge/worktrees/pipeline-e7f78b7a/app/api/git/route.ts +149 -0
  2251. package/.forge/worktrees/pipeline-e7f78b7a/app/api/help/route.ts +84 -0
  2252. package/.forge/worktrees/pipeline-e7f78b7a/app/api/issue-scanner/route.ts +116 -0
  2253. package/.forge/worktrees/pipeline-e7f78b7a/app/api/logs/route.ts +100 -0
  2254. package/.forge/worktrees/pipeline-e7f78b7a/app/api/mobile-chat/route.ts +115 -0
  2255. package/.forge/worktrees/pipeline-e7f78b7a/app/api/monitor/route.ts +74 -0
  2256. package/.forge/worktrees/pipeline-e7f78b7a/app/api/notifications/route.ts +42 -0
  2257. package/.forge/worktrees/pipeline-e7f78b7a/app/api/notify/test/route.ts +33 -0
  2258. package/.forge/worktrees/pipeline-e7f78b7a/app/api/online/route.ts +40 -0
  2259. package/.forge/worktrees/pipeline-e7f78b7a/app/api/pipelines/[id]/route.ts +41 -0
  2260. package/.forge/worktrees/pipeline-e7f78b7a/app/api/pipelines/route.ts +90 -0
  2261. package/.forge/worktrees/pipeline-e7f78b7a/app/api/plugins/route.ts +75 -0
  2262. package/.forge/worktrees/pipeline-e7f78b7a/app/api/preview/[...path]/route.ts +64 -0
  2263. package/.forge/worktrees/pipeline-e7f78b7a/app/api/preview/route.ts +156 -0
  2264. package/.forge/worktrees/pipeline-e7f78b7a/app/api/project-pipelines/route.ts +91 -0
  2265. package/.forge/worktrees/pipeline-e7f78b7a/app/api/project-sessions/route.ts +61 -0
  2266. package/.forge/worktrees/pipeline-e7f78b7a/app/api/projects/route.ts +26 -0
  2267. package/.forge/worktrees/pipeline-e7f78b7a/app/api/sessions/[id]/chat/route.ts +64 -0
  2268. package/.forge/worktrees/pipeline-e7f78b7a/app/api/sessions/[id]/messages/route.ts +9 -0
  2269. package/.forge/worktrees/pipeline-e7f78b7a/app/api/sessions/[id]/route.ts +17 -0
  2270. package/.forge/worktrees/pipeline-e7f78b7a/app/api/sessions/route.ts +20 -0
  2271. package/.forge/worktrees/pipeline-e7f78b7a/app/api/settings/route.ts +64 -0
  2272. package/.forge/worktrees/pipeline-e7f78b7a/app/api/skills/local/route.ts +228 -0
  2273. package/.forge/worktrees/pipeline-e7f78b7a/app/api/skills/route.ts +182 -0
  2274. package/.forge/worktrees/pipeline-e7f78b7a/app/api/smith-templates/route.ts +81 -0
  2275. package/.forge/worktrees/pipeline-e7f78b7a/app/api/status/route.ts +12 -0
  2276. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tabs/route.ts +25 -0
  2277. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tasks/[id]/route.ts +51 -0
  2278. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tasks/[id]/stream/route.ts +77 -0
  2279. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tasks/link/route.ts +37 -0
  2280. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tasks/route.ts +44 -0
  2281. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tasks/session/route.ts +14 -0
  2282. package/.forge/worktrees/pipeline-e7f78b7a/app/api/telegram/route.ts +23 -0
  2283. package/.forge/worktrees/pipeline-e7f78b7a/app/api/templates/route.ts +6 -0
  2284. package/.forge/worktrees/pipeline-e7f78b7a/app/api/terminal-bell/route.ts +35 -0
  2285. package/.forge/worktrees/pipeline-e7f78b7a/app/api/terminal-cwd/route.ts +19 -0
  2286. package/.forge/worktrees/pipeline-e7f78b7a/app/api/terminal-state/route.ts +15 -0
  2287. package/.forge/worktrees/pipeline-e7f78b7a/app/api/tunnel/route.ts +26 -0
  2288. package/.forge/worktrees/pipeline-e7f78b7a/app/api/upgrade/route.ts +43 -0
  2289. package/.forge/worktrees/pipeline-e7f78b7a/app/api/usage/route.ts +20 -0
  2290. package/.forge/worktrees/pipeline-e7f78b7a/app/api/version/route.ts +78 -0
  2291. package/.forge/worktrees/pipeline-e7f78b7a/app/api/watchers/route.ts +33 -0
  2292. package/.forge/worktrees/pipeline-e7f78b7a/app/api/workspace/[id]/agents/route.ts +35 -0
  2293. package/.forge/worktrees/pipeline-e7f78b7a/app/api/workspace/[id]/memory/route.ts +23 -0
  2294. package/.forge/worktrees/pipeline-e7f78b7a/app/api/workspace/[id]/smith/route.ts +22 -0
  2295. package/.forge/worktrees/pipeline-e7f78b7a/app/api/workspace/[id]/stream/route.ts +28 -0
  2296. package/.forge/worktrees/pipeline-e7f78b7a/app/api/workspace/route.ts +100 -0
  2297. package/.forge/worktrees/pipeline-e7f78b7a/app/global-error.tsx +21 -0
  2298. package/.forge/worktrees/pipeline-e7f78b7a/app/globals.css +52 -0
  2299. package/.forge/worktrees/pipeline-e7f78b7a/app/icon.ico +0 -0
  2300. package/.forge/worktrees/pipeline-e7f78b7a/app/icon.png +0 -0
  2301. package/.forge/worktrees/pipeline-e7f78b7a/app/icon.svg +106 -0
  2302. package/.forge/worktrees/pipeline-e7f78b7a/app/layout.tsx +17 -0
  2303. package/.forge/worktrees/pipeline-e7f78b7a/app/login/LoginForm.tsx +96 -0
  2304. package/.forge/worktrees/pipeline-e7f78b7a/app/login/page.tsx +10 -0
  2305. package/.forge/worktrees/pipeline-e7f78b7a/app/mobile/page.tsx +9 -0
  2306. package/.forge/worktrees/pipeline-e7f78b7a/app/page.tsx +21 -0
  2307. package/.forge/worktrees/pipeline-e7f78b7a/bin/forge-server.mjs +484 -0
  2308. package/.forge/worktrees/pipeline-e7f78b7a/check-forge-status.sh +71 -0
  2309. package/.forge/worktrees/pipeline-e7f78b7a/cli/mw.ts +579 -0
  2310. package/.forge/worktrees/pipeline-e7f78b7a/components/BrowserPanel.tsx +175 -0
  2311. package/.forge/worktrees/pipeline-e7f78b7a/components/ChatPanel.tsx +191 -0
  2312. package/.forge/worktrees/pipeline-e7f78b7a/components/ClaudeTerminal.tsx +267 -0
  2313. package/.forge/worktrees/pipeline-e7f78b7a/components/CodeViewer.tsx +787 -0
  2314. package/.forge/worktrees/pipeline-e7f78b7a/components/ConversationEditor.tsx +411 -0
  2315. package/.forge/worktrees/pipeline-e7f78b7a/components/ConversationGraphView.tsx +347 -0
  2316. package/.forge/worktrees/pipeline-e7f78b7a/components/ConversationTerminalView.tsx +303 -0
  2317. package/.forge/worktrees/pipeline-e7f78b7a/components/Dashboard.tsx +807 -0
  2318. package/.forge/worktrees/pipeline-e7f78b7a/components/DashboardWrapper.tsx +9 -0
  2319. package/.forge/worktrees/pipeline-e7f78b7a/components/DeliveryFlowEditor.tsx +491 -0
  2320. package/.forge/worktrees/pipeline-e7f78b7a/components/DeliveryList.tsx +230 -0
  2321. package/.forge/worktrees/pipeline-e7f78b7a/components/DeliveryWorkspace.tsx +589 -0
  2322. package/.forge/worktrees/pipeline-e7f78b7a/components/DocTerminal.tsx +187 -0
  2323. package/.forge/worktrees/pipeline-e7f78b7a/components/DocsViewer.tsx +574 -0
  2324. package/.forge/worktrees/pipeline-e7f78b7a/components/HelpDialog.tsx +169 -0
  2325. package/.forge/worktrees/pipeline-e7f78b7a/components/HelpTerminal.tsx +141 -0
  2326. package/.forge/worktrees/pipeline-e7f78b7a/components/InlinePipelineView.tsx +111 -0
  2327. package/.forge/worktrees/pipeline-e7f78b7a/components/LogViewer.tsx +194 -0
  2328. package/.forge/worktrees/pipeline-e7f78b7a/components/MarkdownContent.tsx +73 -0
  2329. package/.forge/worktrees/pipeline-e7f78b7a/components/MobileView.tsx +385 -0
  2330. package/.forge/worktrees/pipeline-e7f78b7a/components/MonitorPanel.tsx +122 -0
  2331. package/.forge/worktrees/pipeline-e7f78b7a/components/NewSessionModal.tsx +93 -0
  2332. package/.forge/worktrees/pipeline-e7f78b7a/components/NewTaskModal.tsx +492 -0
  2333. package/.forge/worktrees/pipeline-e7f78b7a/components/PipelineEditor.tsx +570 -0
  2334. package/.forge/worktrees/pipeline-e7f78b7a/components/PipelineView.tsx +1018 -0
  2335. package/.forge/worktrees/pipeline-e7f78b7a/components/PluginsPanel.tsx +472 -0
  2336. package/.forge/worktrees/pipeline-e7f78b7a/components/ProjectDetail.tsx +1618 -0
  2337. package/.forge/worktrees/pipeline-e7f78b7a/components/ProjectList.tsx +108 -0
  2338. package/.forge/worktrees/pipeline-e7f78b7a/components/ProjectManager.tsx +401 -0
  2339. package/.forge/worktrees/pipeline-e7f78b7a/components/SessionList.tsx +74 -0
  2340. package/.forge/worktrees/pipeline-e7f78b7a/components/SessionView.tsx +726 -0
  2341. package/.forge/worktrees/pipeline-e7f78b7a/components/SettingsModal.tsx +1647 -0
  2342. package/.forge/worktrees/pipeline-e7f78b7a/components/SkillsPanel.tsx +969 -0
  2343. package/.forge/worktrees/pipeline-e7f78b7a/components/StatusBar.tsx +99 -0
  2344. package/.forge/worktrees/pipeline-e7f78b7a/components/TabBar.tsx +46 -0
  2345. package/.forge/worktrees/pipeline-e7f78b7a/components/TaskBoard.tsx +113 -0
  2346. package/.forge/worktrees/pipeline-e7f78b7a/components/TaskDetail.tsx +372 -0
  2347. package/.forge/worktrees/pipeline-e7f78b7a/components/TerminalLauncher.tsx +398 -0
  2348. package/.forge/worktrees/pipeline-e7f78b7a/components/TunnelToggle.tsx +206 -0
  2349. package/.forge/worktrees/pipeline-e7f78b7a/components/UsagePanel.tsx +207 -0
  2350. package/.forge/worktrees/pipeline-e7f78b7a/components/WebTerminal.tsx +1683 -0
  2351. package/.forge/worktrees/pipeline-e7f78b7a/components/WorkspaceTree.tsx +221 -0
  2352. package/.forge/worktrees/pipeline-e7f78b7a/components/WorkspaceView.tsx +4048 -0
  2353. package/.forge/worktrees/pipeline-e7f78b7a/dev-test.sh +5 -0
  2354. package/.forge/worktrees/pipeline-e7f78b7a/docs/Forge_Memory_Layer_Design.docx +0 -0
  2355. package/.forge/worktrees/pipeline-e7f78b7a/docs/Forge_Strategy_Research_2026.docx +0 -0
  2356. package/.forge/worktrees/pipeline-e7f78b7a/docs/LOCAL-DEPLOY.md +144 -0
  2357. package/.forge/worktrees/pipeline-e7f78b7a/docs/roadmap-multi-agent-workflow.md +330 -0
  2358. package/.forge/worktrees/pipeline-e7f78b7a/forge-logo.png +0 -0
  2359. package/.forge/worktrees/pipeline-e7f78b7a/forge-logo.svg +106 -0
  2360. package/.forge/worktrees/pipeline-e7f78b7a/hooks/useSidebarResize.ts +52 -0
  2361. package/.forge/worktrees/pipeline-e7f78b7a/install.sh +29 -0
  2362. package/.forge/worktrees/pipeline-e7f78b7a/instrumentation.ts +35 -0
  2363. package/.forge/worktrees/pipeline-e7f78b7a/lib/agents/claude-adapter.ts +104 -0
  2364. package/.forge/worktrees/pipeline-e7f78b7a/lib/agents/generic-adapter.ts +64 -0
  2365. package/.forge/worktrees/pipeline-e7f78b7a/lib/agents/index.ts +245 -0
  2366. package/.forge/worktrees/pipeline-e7f78b7a/lib/agents/types.ts +70 -0
  2367. package/.forge/worktrees/pipeline-e7f78b7a/lib/artifacts.ts +106 -0
  2368. package/.forge/worktrees/pipeline-e7f78b7a/lib/auth.ts +62 -0
  2369. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/docker.yaml +70 -0
  2370. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/http.yaml +66 -0
  2371. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/jenkins.yaml +92 -0
  2372. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/llm-vision.yaml +85 -0
  2373. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/playwright.yaml +111 -0
  2374. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/shell-command.yaml +60 -0
  2375. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/slack.yaml +48 -0
  2376. package/.forge/worktrees/pipeline-e7f78b7a/lib/builtin-plugins/webhook.yaml +56 -0
  2377. package/.forge/worktrees/pipeline-e7f78b7a/lib/claude-process.ts +352 -0
  2378. package/.forge/worktrees/pipeline-e7f78b7a/lib/claude-sessions.ts +266 -0
  2379. package/.forge/worktrees/pipeline-e7f78b7a/lib/claude-templates.ts +227 -0
  2380. package/.forge/worktrees/pipeline-e7f78b7a/lib/cloudflared.ts +424 -0
  2381. package/.forge/worktrees/pipeline-e7f78b7a/lib/crypto.ts +67 -0
  2382. package/.forge/worktrees/pipeline-e7f78b7a/lib/delivery.ts +787 -0
  2383. package/.forge/worktrees/pipeline-e7f78b7a/lib/dirs.ts +99 -0
  2384. package/.forge/worktrees/pipeline-e7f78b7a/lib/flows.ts +86 -0
  2385. package/.forge/worktrees/pipeline-e7f78b7a/lib/forge-mcp-server.ts +717 -0
  2386. package/.forge/worktrees/pipeline-e7f78b7a/lib/forge-skills/forge-inbox.md +38 -0
  2387. package/.forge/worktrees/pipeline-e7f78b7a/lib/forge-skills/forge-send.md +47 -0
  2388. package/.forge/worktrees/pipeline-e7f78b7a/lib/forge-skills/forge-status.md +32 -0
  2389. package/.forge/worktrees/pipeline-e7f78b7a/lib/forge-skills/forge-workspace-sync.md +37 -0
  2390. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/00-overview.md +40 -0
  2391. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/01-settings.md +194 -0
  2392. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/02-telegram.md +41 -0
  2393. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/03-tunnel.md +31 -0
  2394. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/04-tasks.md +52 -0
  2395. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/05-pipelines.md +460 -0
  2396. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/06-skills.md +43 -0
  2397. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/07-projects.md +73 -0
  2398. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/08-rules.md +53 -0
  2399. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/09-issue-autofix.md +55 -0
  2400. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/10-troubleshooting.md +89 -0
  2401. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/11-workspace.md +810 -0
  2402. package/.forge/worktrees/pipeline-e7f78b7a/lib/help-docs/CLAUDE.md +62 -0
  2403. package/.forge/worktrees/pipeline-e7f78b7a/lib/init.ts +266 -0
  2404. package/.forge/worktrees/pipeline-e7f78b7a/lib/issue-scanner.ts +298 -0
  2405. package/.forge/worktrees/pipeline-e7f78b7a/lib/logger.ts +79 -0
  2406. package/.forge/worktrees/pipeline-e7f78b7a/lib/notifications.ts +75 -0
  2407. package/.forge/worktrees/pipeline-e7f78b7a/lib/notify.ts +108 -0
  2408. package/.forge/worktrees/pipeline-e7f78b7a/lib/password.ts +97 -0
  2409. package/.forge/worktrees/pipeline-e7f78b7a/lib/pipeline-scheduler.ts +373 -0
  2410. package/.forge/worktrees/pipeline-e7f78b7a/lib/pipeline.ts +1441 -0
  2411. package/.forge/worktrees/pipeline-e7f78b7a/lib/plugins/executor.ts +347 -0
  2412. package/.forge/worktrees/pipeline-e7f78b7a/lib/plugins/registry.ts +228 -0
  2413. package/.forge/worktrees/pipeline-e7f78b7a/lib/plugins/types.ts +103 -0
  2414. package/.forge/worktrees/pipeline-e7f78b7a/lib/project-sessions.ts +53 -0
  2415. package/.forge/worktrees/pipeline-e7f78b7a/lib/projects.ts +86 -0
  2416. package/.forge/worktrees/pipeline-e7f78b7a/lib/session-manager.ts +156 -0
  2417. package/.forge/worktrees/pipeline-e7f78b7a/lib/session-utils.ts +53 -0
  2418. package/.forge/worktrees/pipeline-e7f78b7a/lib/session-watcher.ts +345 -0
  2419. package/.forge/worktrees/pipeline-e7f78b7a/lib/settings.ts +195 -0
  2420. package/.forge/worktrees/pipeline-e7f78b7a/lib/skills.ts +458 -0
  2421. package/.forge/worktrees/pipeline-e7f78b7a/lib/task-manager.ts +949 -0
  2422. package/.forge/worktrees/pipeline-e7f78b7a/lib/telegram-bot.ts +1477 -0
  2423. package/.forge/worktrees/pipeline-e7f78b7a/lib/telegram-standalone.ts +83 -0
  2424. package/.forge/worktrees/pipeline-e7f78b7a/lib/terminal-server.ts +70 -0
  2425. package/.forge/worktrees/pipeline-e7f78b7a/lib/terminal-standalone.ts +421 -0
  2426. package/.forge/worktrees/pipeline-e7f78b7a/lib/usage-scanner.ts +249 -0
  2427. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/__tests__/state-machine.test.ts +388 -0
  2428. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/__tests__/workspace.test.ts +311 -0
  2429. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/agent-bus.ts +416 -0
  2430. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/agent-worker.ts +655 -0
  2431. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/backends/api-backend.ts +262 -0
  2432. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/backends/cli-backend.ts +491 -0
  2433. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/index.ts +82 -0
  2434. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/manager.ts +136 -0
  2435. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/orchestrator.ts +3400 -0
  2436. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/persistence.ts +309 -0
  2437. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/presets.ts +649 -0
  2438. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/requests.ts +287 -0
  2439. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/session-monitor.ts +240 -0
  2440. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/skill-installer.ts +275 -0
  2441. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/smith-memory.ts +498 -0
  2442. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/types.ts +241 -0
  2443. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace/watch-manager.ts +560 -0
  2444. package/.forge/worktrees/pipeline-e7f78b7a/lib/workspace-standalone.ts +911 -0
  2445. package/.forge/worktrees/pipeline-e7f78b7a/middleware.ts +51 -0
  2446. package/.forge/worktrees/pipeline-e7f78b7a/next.config.ts +26 -0
  2447. package/.forge/worktrees/pipeline-e7f78b7a/package.json +74 -0
  2448. package/.forge/worktrees/pipeline-e7f78b7a/pnpm-lock.yaml +3719 -0
  2449. package/.forge/worktrees/pipeline-e7f78b7a/pnpm-workspace.yaml +1 -0
  2450. package/.forge/worktrees/pipeline-e7f78b7a/postcss.config.mjs +7 -0
  2451. package/.forge/worktrees/pipeline-e7f78b7a/publish.sh +133 -0
  2452. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/README.md +66 -0
  2453. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/results/.gitignore +2 -0
  2454. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/run.ts +635 -0
  2455. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/01-text-utils/task.md +26 -0
  2456. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  2457. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  2458. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/02-pagination/task.md +48 -0
  2459. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  2460. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  2461. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  2462. package/.forge/worktrees/pipeline-e7f78b7a/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  2463. package/.forge/worktrees/pipeline-e7f78b7a/scripts/verify-usage.ts +178 -0
  2464. package/.forge/worktrees/pipeline-e7f78b7a/src/config/index.ts +129 -0
  2465. package/.forge/worktrees/pipeline-e7f78b7a/src/core/db/database.ts +259 -0
  2466. package/.forge/worktrees/pipeline-e7f78b7a/src/core/memory/strategy.ts +32 -0
  2467. package/.forge/worktrees/pipeline-e7f78b7a/src/core/providers/chat.ts +65 -0
  2468. package/.forge/worktrees/pipeline-e7f78b7a/src/core/providers/registry.ts +60 -0
  2469. package/.forge/worktrees/pipeline-e7f78b7a/src/core/session/manager.ts +190 -0
  2470. package/.forge/worktrees/pipeline-e7f78b7a/src/types/index.ts +129 -0
  2471. package/.forge/worktrees/pipeline-e7f78b7a/start.sh +31 -0
  2472. package/.forge/worktrees/pipeline-e7f78b7a/templates/smith-lead.json +45 -0
  2473. package/.forge/worktrees/pipeline-e7f78b7a/tsconfig.json +42 -0
  2474. package/.forge/worktrees/pipeline-e97c13c7/CLAUDE.md +86 -0
  2475. package/.forge/worktrees/pipeline-e97c13c7/README.md +136 -0
  2476. package/.forge/worktrees/pipeline-e97c13c7/RELEASE_NOTES.md +11 -0
  2477. package/.forge/worktrees/pipeline-e97c13c7/app/api/agents/route.ts +17 -0
  2478. package/.forge/worktrees/pipeline-e97c13c7/app/api/auth/[...nextauth]/route.ts +3 -0
  2479. package/.forge/worktrees/pipeline-e97c13c7/app/api/auth/verify/route.ts +46 -0
  2480. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude/[id]/route.ts +31 -0
  2481. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude/[id]/stream/route.ts +63 -0
  2482. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude/route.ts +28 -0
  2483. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  2484. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  2485. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude-sessions/[projectName]/route.ts +37 -0
  2486. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude-sessions/sync/route.ts +17 -0
  2487. package/.forge/worktrees/pipeline-e97c13c7/app/api/claude-templates/route.ts +145 -0
  2488. package/.forge/worktrees/pipeline-e97c13c7/app/api/code/route.ts +299 -0
  2489. package/.forge/worktrees/pipeline-e97c13c7/app/api/delivery/[id]/route.ts +62 -0
  2490. package/.forge/worktrees/pipeline-e97c13c7/app/api/delivery/route.ts +40 -0
  2491. package/.forge/worktrees/pipeline-e97c13c7/app/api/detect-cli/route.ts +46 -0
  2492. package/.forge/worktrees/pipeline-e97c13c7/app/api/docs/route.ts +176 -0
  2493. package/.forge/worktrees/pipeline-e97c13c7/app/api/docs/sessions/route.ts +54 -0
  2494. package/.forge/worktrees/pipeline-e97c13c7/app/api/favorites/route.ts +26 -0
  2495. package/.forge/worktrees/pipeline-e97c13c7/app/api/flows/route.ts +6 -0
  2496. package/.forge/worktrees/pipeline-e97c13c7/app/api/flows/run/route.ts +19 -0
  2497. package/.forge/worktrees/pipeline-e97c13c7/app/api/git/route.ts +149 -0
  2498. package/.forge/worktrees/pipeline-e97c13c7/app/api/help/route.ts +84 -0
  2499. package/.forge/worktrees/pipeline-e97c13c7/app/api/issue-scanner/route.ts +116 -0
  2500. package/.forge/worktrees/pipeline-e97c13c7/app/api/logs/route.ts +100 -0
  2501. package/.forge/worktrees/pipeline-e97c13c7/app/api/mobile-chat/route.ts +115 -0
  2502. package/.forge/worktrees/pipeline-e97c13c7/app/api/monitor/route.ts +74 -0
  2503. package/.forge/worktrees/pipeline-e97c13c7/app/api/notifications/route.ts +42 -0
  2504. package/.forge/worktrees/pipeline-e97c13c7/app/api/notify/test/route.ts +33 -0
  2505. package/.forge/worktrees/pipeline-e97c13c7/app/api/online/route.ts +40 -0
  2506. package/.forge/worktrees/pipeline-e97c13c7/app/api/pipelines/[id]/route.ts +41 -0
  2507. package/.forge/worktrees/pipeline-e97c13c7/app/api/pipelines/route.ts +90 -0
  2508. package/.forge/worktrees/pipeline-e97c13c7/app/api/plugins/route.ts +75 -0
  2509. package/.forge/worktrees/pipeline-e97c13c7/app/api/preview/[...path]/route.ts +64 -0
  2510. package/.forge/worktrees/pipeline-e97c13c7/app/api/preview/route.ts +156 -0
  2511. package/.forge/worktrees/pipeline-e97c13c7/app/api/project-pipelines/route.ts +91 -0
  2512. package/.forge/worktrees/pipeline-e97c13c7/app/api/project-sessions/route.ts +61 -0
  2513. package/.forge/worktrees/pipeline-e97c13c7/app/api/projects/route.ts +26 -0
  2514. package/.forge/worktrees/pipeline-e97c13c7/app/api/sessions/[id]/chat/route.ts +64 -0
  2515. package/.forge/worktrees/pipeline-e97c13c7/app/api/sessions/[id]/messages/route.ts +9 -0
  2516. package/.forge/worktrees/pipeline-e97c13c7/app/api/sessions/[id]/route.ts +17 -0
  2517. package/.forge/worktrees/pipeline-e97c13c7/app/api/sessions/route.ts +20 -0
  2518. package/.forge/worktrees/pipeline-e97c13c7/app/api/settings/route.ts +64 -0
  2519. package/.forge/worktrees/pipeline-e97c13c7/app/api/skills/local/route.ts +228 -0
  2520. package/.forge/worktrees/pipeline-e97c13c7/app/api/skills/route.ts +182 -0
  2521. package/.forge/worktrees/pipeline-e97c13c7/app/api/smith-templates/route.ts +81 -0
  2522. package/.forge/worktrees/pipeline-e97c13c7/app/api/status/route.ts +12 -0
  2523. package/.forge/worktrees/pipeline-e97c13c7/app/api/tabs/route.ts +25 -0
  2524. package/.forge/worktrees/pipeline-e97c13c7/app/api/tasks/[id]/route.ts +51 -0
  2525. package/.forge/worktrees/pipeline-e97c13c7/app/api/tasks/[id]/stream/route.ts +77 -0
  2526. package/.forge/worktrees/pipeline-e97c13c7/app/api/tasks/link/route.ts +37 -0
  2527. package/.forge/worktrees/pipeline-e97c13c7/app/api/tasks/route.ts +44 -0
  2528. package/.forge/worktrees/pipeline-e97c13c7/app/api/tasks/session/route.ts +14 -0
  2529. package/.forge/worktrees/pipeline-e97c13c7/app/api/telegram/route.ts +23 -0
  2530. package/.forge/worktrees/pipeline-e97c13c7/app/api/templates/route.ts +6 -0
  2531. package/.forge/worktrees/pipeline-e97c13c7/app/api/terminal-bell/route.ts +35 -0
  2532. package/.forge/worktrees/pipeline-e97c13c7/app/api/terminal-cwd/route.ts +19 -0
  2533. package/.forge/worktrees/pipeline-e97c13c7/app/api/terminal-state/route.ts +15 -0
  2534. package/.forge/worktrees/pipeline-e97c13c7/app/api/tunnel/route.ts +26 -0
  2535. package/.forge/worktrees/pipeline-e97c13c7/app/api/upgrade/route.ts +43 -0
  2536. package/.forge/worktrees/pipeline-e97c13c7/app/api/usage/route.ts +20 -0
  2537. package/.forge/worktrees/pipeline-e97c13c7/app/api/version/route.ts +78 -0
  2538. package/.forge/worktrees/pipeline-e97c13c7/app/api/watchers/route.ts +33 -0
  2539. package/.forge/worktrees/pipeline-e97c13c7/app/api/workspace/[id]/agents/route.ts +35 -0
  2540. package/.forge/worktrees/pipeline-e97c13c7/app/api/workspace/[id]/memory/route.ts +23 -0
  2541. package/.forge/worktrees/pipeline-e97c13c7/app/api/workspace/[id]/smith/route.ts +22 -0
  2542. package/.forge/worktrees/pipeline-e97c13c7/app/api/workspace/[id]/stream/route.ts +28 -0
  2543. package/.forge/worktrees/pipeline-e97c13c7/app/api/workspace/route.ts +100 -0
  2544. package/.forge/worktrees/pipeline-e97c13c7/app/global-error.tsx +21 -0
  2545. package/.forge/worktrees/pipeline-e97c13c7/app/globals.css +52 -0
  2546. package/.forge/worktrees/pipeline-e97c13c7/app/icon.ico +0 -0
  2547. package/.forge/worktrees/pipeline-e97c13c7/app/icon.png +0 -0
  2548. package/.forge/worktrees/pipeline-e97c13c7/app/icon.svg +106 -0
  2549. package/.forge/worktrees/pipeline-e97c13c7/app/layout.tsx +17 -0
  2550. package/.forge/worktrees/pipeline-e97c13c7/app/login/LoginForm.tsx +96 -0
  2551. package/.forge/worktrees/pipeline-e97c13c7/app/login/page.tsx +10 -0
  2552. package/.forge/worktrees/pipeline-e97c13c7/app/mobile/page.tsx +9 -0
  2553. package/.forge/worktrees/pipeline-e97c13c7/app/page.tsx +21 -0
  2554. package/.forge/worktrees/pipeline-e97c13c7/bin/forge-server.mjs +484 -0
  2555. package/.forge/worktrees/pipeline-e97c13c7/check-forge-status.sh +71 -0
  2556. package/.forge/worktrees/pipeline-e97c13c7/cli/mw.ts +579 -0
  2557. package/.forge/worktrees/pipeline-e97c13c7/components/BrowserPanel.tsx +175 -0
  2558. package/.forge/worktrees/pipeline-e97c13c7/components/ChatPanel.tsx +191 -0
  2559. package/.forge/worktrees/pipeline-e97c13c7/components/ClaudeTerminal.tsx +267 -0
  2560. package/.forge/worktrees/pipeline-e97c13c7/components/CodeViewer.tsx +787 -0
  2561. package/.forge/worktrees/pipeline-e97c13c7/components/ConversationEditor.tsx +411 -0
  2562. package/.forge/worktrees/pipeline-e97c13c7/components/ConversationGraphView.tsx +347 -0
  2563. package/.forge/worktrees/pipeline-e97c13c7/components/ConversationTerminalView.tsx +303 -0
  2564. package/.forge/worktrees/pipeline-e97c13c7/components/Dashboard.tsx +807 -0
  2565. package/.forge/worktrees/pipeline-e97c13c7/components/DashboardWrapper.tsx +9 -0
  2566. package/.forge/worktrees/pipeline-e97c13c7/components/DeliveryFlowEditor.tsx +491 -0
  2567. package/.forge/worktrees/pipeline-e97c13c7/components/DeliveryList.tsx +230 -0
  2568. package/.forge/worktrees/pipeline-e97c13c7/components/DeliveryWorkspace.tsx +589 -0
  2569. package/.forge/worktrees/pipeline-e97c13c7/components/DocTerminal.tsx +187 -0
  2570. package/.forge/worktrees/pipeline-e97c13c7/components/DocsViewer.tsx +574 -0
  2571. package/.forge/worktrees/pipeline-e97c13c7/components/HelpDialog.tsx +169 -0
  2572. package/.forge/worktrees/pipeline-e97c13c7/components/HelpTerminal.tsx +141 -0
  2573. package/.forge/worktrees/pipeline-e97c13c7/components/InlinePipelineView.tsx +111 -0
  2574. package/.forge/worktrees/pipeline-e97c13c7/components/LogViewer.tsx +194 -0
  2575. package/.forge/worktrees/pipeline-e97c13c7/components/MarkdownContent.tsx +73 -0
  2576. package/.forge/worktrees/pipeline-e97c13c7/components/MobileView.tsx +385 -0
  2577. package/.forge/worktrees/pipeline-e97c13c7/components/MonitorPanel.tsx +122 -0
  2578. package/.forge/worktrees/pipeline-e97c13c7/components/NewSessionModal.tsx +93 -0
  2579. package/.forge/worktrees/pipeline-e97c13c7/components/NewTaskModal.tsx +492 -0
  2580. package/.forge/worktrees/pipeline-e97c13c7/components/PipelineEditor.tsx +570 -0
  2581. package/.forge/worktrees/pipeline-e97c13c7/components/PipelineView.tsx +1018 -0
  2582. package/.forge/worktrees/pipeline-e97c13c7/components/PluginsPanel.tsx +472 -0
  2583. package/.forge/worktrees/pipeline-e97c13c7/components/ProjectDetail.tsx +1618 -0
  2584. package/.forge/worktrees/pipeline-e97c13c7/components/ProjectList.tsx +108 -0
  2585. package/.forge/worktrees/pipeline-e97c13c7/components/ProjectManager.tsx +401 -0
  2586. package/.forge/worktrees/pipeline-e97c13c7/components/SessionList.tsx +74 -0
  2587. package/.forge/worktrees/pipeline-e97c13c7/components/SessionView.tsx +726 -0
  2588. package/.forge/worktrees/pipeline-e97c13c7/components/SettingsModal.tsx +1647 -0
  2589. package/.forge/worktrees/pipeline-e97c13c7/components/SkillsPanel.tsx +969 -0
  2590. package/.forge/worktrees/pipeline-e97c13c7/components/StatusBar.tsx +99 -0
  2591. package/.forge/worktrees/pipeline-e97c13c7/components/TabBar.tsx +46 -0
  2592. package/.forge/worktrees/pipeline-e97c13c7/components/TaskBoard.tsx +113 -0
  2593. package/.forge/worktrees/pipeline-e97c13c7/components/TaskDetail.tsx +372 -0
  2594. package/.forge/worktrees/pipeline-e97c13c7/components/TerminalLauncher.tsx +398 -0
  2595. package/.forge/worktrees/pipeline-e97c13c7/components/TunnelToggle.tsx +206 -0
  2596. package/.forge/worktrees/pipeline-e97c13c7/components/UsagePanel.tsx +207 -0
  2597. package/.forge/worktrees/pipeline-e97c13c7/components/WebTerminal.tsx +1683 -0
  2598. package/.forge/worktrees/pipeline-e97c13c7/components/WorkspaceTree.tsx +221 -0
  2599. package/.forge/worktrees/pipeline-e97c13c7/components/WorkspaceView.tsx +4048 -0
  2600. package/.forge/worktrees/pipeline-e97c13c7/dev-test.sh +5 -0
  2601. package/.forge/worktrees/pipeline-e97c13c7/docs/Forge_Memory_Layer_Design.docx +0 -0
  2602. package/.forge/worktrees/pipeline-e97c13c7/docs/Forge_Strategy_Research_2026.docx +0 -0
  2603. package/.forge/worktrees/pipeline-e97c13c7/docs/LOCAL-DEPLOY.md +144 -0
  2604. package/.forge/worktrees/pipeline-e97c13c7/docs/roadmap-multi-agent-workflow.md +330 -0
  2605. package/.forge/worktrees/pipeline-e97c13c7/forge-logo.png +0 -0
  2606. package/.forge/worktrees/pipeline-e97c13c7/forge-logo.svg +106 -0
  2607. package/.forge/worktrees/pipeline-e97c13c7/hooks/useSidebarResize.ts +52 -0
  2608. package/.forge/worktrees/pipeline-e97c13c7/install.sh +29 -0
  2609. package/.forge/worktrees/pipeline-e97c13c7/instrumentation.ts +35 -0
  2610. package/.forge/worktrees/pipeline-e97c13c7/lib/agents/claude-adapter.ts +104 -0
  2611. package/.forge/worktrees/pipeline-e97c13c7/lib/agents/generic-adapter.ts +64 -0
  2612. package/.forge/worktrees/pipeline-e97c13c7/lib/agents/index.ts +245 -0
  2613. package/.forge/worktrees/pipeline-e97c13c7/lib/agents/types.ts +70 -0
  2614. package/.forge/worktrees/pipeline-e97c13c7/lib/artifacts.ts +106 -0
  2615. package/.forge/worktrees/pipeline-e97c13c7/lib/auth.ts +62 -0
  2616. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/docker.yaml +70 -0
  2617. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/http.yaml +66 -0
  2618. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/jenkins.yaml +92 -0
  2619. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/llm-vision.yaml +85 -0
  2620. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/playwright.yaml +111 -0
  2621. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/shell-command.yaml +60 -0
  2622. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/slack.yaml +48 -0
  2623. package/.forge/worktrees/pipeline-e97c13c7/lib/builtin-plugins/webhook.yaml +56 -0
  2624. package/.forge/worktrees/pipeline-e97c13c7/lib/claude-process.ts +352 -0
  2625. package/.forge/worktrees/pipeline-e97c13c7/lib/claude-sessions.ts +266 -0
  2626. package/.forge/worktrees/pipeline-e97c13c7/lib/claude-templates.ts +227 -0
  2627. package/.forge/worktrees/pipeline-e97c13c7/lib/cloudflared.ts +424 -0
  2628. package/.forge/worktrees/pipeline-e97c13c7/lib/crypto.ts +67 -0
  2629. package/.forge/worktrees/pipeline-e97c13c7/lib/delivery.ts +787 -0
  2630. package/.forge/worktrees/pipeline-e97c13c7/lib/dirs.ts +99 -0
  2631. package/.forge/worktrees/pipeline-e97c13c7/lib/flows.ts +86 -0
  2632. package/.forge/worktrees/pipeline-e97c13c7/lib/forge-mcp-server.ts +717 -0
  2633. package/.forge/worktrees/pipeline-e97c13c7/lib/forge-skills/forge-inbox.md +38 -0
  2634. package/.forge/worktrees/pipeline-e97c13c7/lib/forge-skills/forge-send.md +47 -0
  2635. package/.forge/worktrees/pipeline-e97c13c7/lib/forge-skills/forge-status.md +32 -0
  2636. package/.forge/worktrees/pipeline-e97c13c7/lib/forge-skills/forge-workspace-sync.md +37 -0
  2637. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/00-overview.md +40 -0
  2638. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/01-settings.md +194 -0
  2639. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/02-telegram.md +41 -0
  2640. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/03-tunnel.md +31 -0
  2641. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/04-tasks.md +52 -0
  2642. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/05-pipelines.md +460 -0
  2643. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/06-skills.md +43 -0
  2644. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/07-projects.md +73 -0
  2645. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/08-rules.md +53 -0
  2646. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/09-issue-autofix.md +55 -0
  2647. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/10-troubleshooting.md +89 -0
  2648. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/11-workspace.md +810 -0
  2649. package/.forge/worktrees/pipeline-e97c13c7/lib/help-docs/CLAUDE.md +62 -0
  2650. package/.forge/worktrees/pipeline-e97c13c7/lib/init.ts +266 -0
  2651. package/.forge/worktrees/pipeline-e97c13c7/lib/issue-scanner.ts +298 -0
  2652. package/.forge/worktrees/pipeline-e97c13c7/lib/logger.ts +79 -0
  2653. package/.forge/worktrees/pipeline-e97c13c7/lib/notifications.ts +75 -0
  2654. package/.forge/worktrees/pipeline-e97c13c7/lib/notify.ts +108 -0
  2655. package/.forge/worktrees/pipeline-e97c13c7/lib/password.ts +97 -0
  2656. package/.forge/worktrees/pipeline-e97c13c7/lib/pipeline-scheduler.ts +373 -0
  2657. package/.forge/worktrees/pipeline-e97c13c7/lib/pipeline.ts +1438 -0
  2658. package/.forge/worktrees/pipeline-e97c13c7/lib/plugins/executor.ts +347 -0
  2659. package/.forge/worktrees/pipeline-e97c13c7/lib/plugins/registry.ts +228 -0
  2660. package/.forge/worktrees/pipeline-e97c13c7/lib/plugins/types.ts +103 -0
  2661. package/.forge/worktrees/pipeline-e97c13c7/lib/project-sessions.ts +53 -0
  2662. package/.forge/worktrees/pipeline-e97c13c7/lib/projects.ts +86 -0
  2663. package/.forge/worktrees/pipeline-e97c13c7/lib/session-manager.ts +156 -0
  2664. package/.forge/worktrees/pipeline-e97c13c7/lib/session-utils.ts +53 -0
  2665. package/.forge/worktrees/pipeline-e97c13c7/lib/session-watcher.ts +345 -0
  2666. package/.forge/worktrees/pipeline-e97c13c7/lib/settings.ts +195 -0
  2667. package/.forge/worktrees/pipeline-e97c13c7/lib/skills.ts +458 -0
  2668. package/.forge/worktrees/pipeline-e97c13c7/lib/task-manager.ts +949 -0
  2669. package/.forge/worktrees/pipeline-e97c13c7/lib/telegram-bot.ts +1477 -0
  2670. package/.forge/worktrees/pipeline-e97c13c7/lib/telegram-standalone.ts +83 -0
  2671. package/.forge/worktrees/pipeline-e97c13c7/lib/terminal-server.ts +70 -0
  2672. package/.forge/worktrees/pipeline-e97c13c7/lib/terminal-standalone.ts +421 -0
  2673. package/.forge/worktrees/pipeline-e97c13c7/lib/usage-scanner.ts +249 -0
  2674. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/__tests__/state-machine.test.ts +388 -0
  2675. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/__tests__/workspace.test.ts +311 -0
  2676. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/agent-bus.ts +416 -0
  2677. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/agent-worker.ts +655 -0
  2678. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/backends/api-backend.ts +262 -0
  2679. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/backends/cli-backend.ts +491 -0
  2680. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/index.ts +82 -0
  2681. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/manager.ts +136 -0
  2682. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/orchestrator.ts +3400 -0
  2683. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/persistence.ts +309 -0
  2684. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/presets.ts +649 -0
  2685. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/requests.ts +287 -0
  2686. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/session-monitor.ts +240 -0
  2687. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/skill-installer.ts +275 -0
  2688. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/smith-memory.ts +498 -0
  2689. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/types.ts +241 -0
  2690. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace/watch-manager.ts +560 -0
  2691. package/.forge/worktrees/pipeline-e97c13c7/lib/workspace-standalone.ts +911 -0
  2692. package/.forge/worktrees/pipeline-e97c13c7/middleware.ts +51 -0
  2693. package/.forge/worktrees/pipeline-e97c13c7/next.config.ts +26 -0
  2694. package/.forge/worktrees/pipeline-e97c13c7/package.json +74 -0
  2695. package/.forge/worktrees/pipeline-e97c13c7/pnpm-lock.yaml +3719 -0
  2696. package/.forge/worktrees/pipeline-e97c13c7/pnpm-workspace.yaml +1 -0
  2697. package/.forge/worktrees/pipeline-e97c13c7/postcss.config.mjs +7 -0
  2698. package/.forge/worktrees/pipeline-e97c13c7/publish.sh +133 -0
  2699. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/README.md +66 -0
  2700. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/results/.gitignore +2 -0
  2701. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/run.ts +635 -0
  2702. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/01-text-utils/task.md +26 -0
  2703. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  2704. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  2705. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/02-pagination/task.md +48 -0
  2706. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  2707. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  2708. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  2709. package/.forge/worktrees/pipeline-e97c13c7/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  2710. package/.forge/worktrees/pipeline-e97c13c7/scripts/verify-usage.ts +178 -0
  2711. package/.forge/worktrees/pipeline-e97c13c7/src/config/index.ts +129 -0
  2712. package/.forge/worktrees/pipeline-e97c13c7/src/core/db/database.ts +259 -0
  2713. package/.forge/worktrees/pipeline-e97c13c7/src/core/memory/strategy.ts +32 -0
  2714. package/.forge/worktrees/pipeline-e97c13c7/src/core/providers/chat.ts +65 -0
  2715. package/.forge/worktrees/pipeline-e97c13c7/src/core/providers/registry.ts +60 -0
  2716. package/.forge/worktrees/pipeline-e97c13c7/src/core/session/manager.ts +190 -0
  2717. package/.forge/worktrees/pipeline-e97c13c7/src/types/index.ts +129 -0
  2718. package/.forge/worktrees/pipeline-e97c13c7/start.sh +31 -0
  2719. package/.forge/worktrees/pipeline-e97c13c7/templates/smith-lead.json +45 -0
  2720. package/.forge/worktrees/pipeline-e97c13c7/tsconfig.json +42 -0
  2721. package/.forge/worktrees/pipeline-ecd7cb0f/CLAUDE.md +86 -0
  2722. package/.forge/worktrees/pipeline-ecd7cb0f/README.md +136 -0
  2723. package/.forge/worktrees/pipeline-ecd7cb0f/RELEASE_NOTES.md +11 -0
  2724. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/agents/route.ts +17 -0
  2725. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/auth/[...nextauth]/route.ts +3 -0
  2726. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/auth/verify/route.ts +46 -0
  2727. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude/[id]/route.ts +31 -0
  2728. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude/[id]/stream/route.ts +63 -0
  2729. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude/route.ts +28 -0
  2730. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  2731. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  2732. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude-sessions/[projectName]/route.ts +37 -0
  2733. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude-sessions/sync/route.ts +17 -0
  2734. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/claude-templates/route.ts +145 -0
  2735. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/code/route.ts +299 -0
  2736. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/delivery/[id]/route.ts +62 -0
  2737. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/delivery/route.ts +40 -0
  2738. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/detect-cli/route.ts +46 -0
  2739. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/docs/route.ts +176 -0
  2740. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/docs/sessions/route.ts +54 -0
  2741. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/favorites/route.ts +26 -0
  2742. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/flows/route.ts +6 -0
  2743. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/flows/run/route.ts +19 -0
  2744. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/git/route.ts +149 -0
  2745. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/help/route.ts +84 -0
  2746. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/issue-scanner/route.ts +116 -0
  2747. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/logs/route.ts +100 -0
  2748. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/mobile-chat/route.ts +115 -0
  2749. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/monitor/route.ts +74 -0
  2750. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/notifications/route.ts +42 -0
  2751. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/notify/test/route.ts +33 -0
  2752. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/online/route.ts +40 -0
  2753. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/pipelines/[id]/route.ts +41 -0
  2754. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/pipelines/route.ts +90 -0
  2755. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/plugins/route.ts +75 -0
  2756. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/preview/[...path]/route.ts +64 -0
  2757. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/preview/route.ts +156 -0
  2758. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/project-pipelines/route.ts +91 -0
  2759. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/project-sessions/route.ts +61 -0
  2760. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/projects/route.ts +26 -0
  2761. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/sessions/[id]/chat/route.ts +64 -0
  2762. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/sessions/[id]/messages/route.ts +9 -0
  2763. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/sessions/[id]/route.ts +17 -0
  2764. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/sessions/route.ts +20 -0
  2765. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/settings/route.ts +64 -0
  2766. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/skills/local/route.ts +228 -0
  2767. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/skills/route.ts +182 -0
  2768. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/smith-templates/route.ts +81 -0
  2769. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/status/route.ts +12 -0
  2770. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tabs/route.ts +25 -0
  2771. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tasks/[id]/route.ts +51 -0
  2772. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tasks/[id]/stream/route.ts +77 -0
  2773. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tasks/link/route.ts +37 -0
  2774. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tasks/route.ts +44 -0
  2775. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tasks/session/route.ts +14 -0
  2776. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/telegram/route.ts +23 -0
  2777. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/templates/route.ts +6 -0
  2778. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/terminal-bell/route.ts +35 -0
  2779. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/terminal-cwd/route.ts +19 -0
  2780. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/terminal-state/route.ts +15 -0
  2781. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/tunnel/route.ts +26 -0
  2782. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/upgrade/route.ts +43 -0
  2783. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/usage/route.ts +20 -0
  2784. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/version/route.ts +78 -0
  2785. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/watchers/route.ts +33 -0
  2786. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/workspace/[id]/agents/route.ts +35 -0
  2787. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/workspace/[id]/memory/route.ts +23 -0
  2788. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/workspace/[id]/smith/route.ts +22 -0
  2789. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/workspace/[id]/stream/route.ts +28 -0
  2790. package/.forge/worktrees/pipeline-ecd7cb0f/app/api/workspace/route.ts +100 -0
  2791. package/.forge/worktrees/pipeline-ecd7cb0f/app/global-error.tsx +21 -0
  2792. package/.forge/worktrees/pipeline-ecd7cb0f/app/globals.css +52 -0
  2793. package/.forge/worktrees/pipeline-ecd7cb0f/app/icon.ico +0 -0
  2794. package/.forge/worktrees/pipeline-ecd7cb0f/app/icon.png +0 -0
  2795. package/.forge/worktrees/pipeline-ecd7cb0f/app/icon.svg +106 -0
  2796. package/.forge/worktrees/pipeline-ecd7cb0f/app/layout.tsx +17 -0
  2797. package/.forge/worktrees/pipeline-ecd7cb0f/app/login/LoginForm.tsx +96 -0
  2798. package/.forge/worktrees/pipeline-ecd7cb0f/app/login/page.tsx +10 -0
  2799. package/.forge/worktrees/pipeline-ecd7cb0f/app/mobile/page.tsx +9 -0
  2800. package/.forge/worktrees/pipeline-ecd7cb0f/app/page.tsx +21 -0
  2801. package/.forge/worktrees/pipeline-ecd7cb0f/bin/forge-server.mjs +484 -0
  2802. package/.forge/worktrees/pipeline-ecd7cb0f/check-forge-status.sh +71 -0
  2803. package/.forge/worktrees/pipeline-ecd7cb0f/cli/mw.ts +579 -0
  2804. package/.forge/worktrees/pipeline-ecd7cb0f/components/BrowserPanel.tsx +175 -0
  2805. package/.forge/worktrees/pipeline-ecd7cb0f/components/ChatPanel.tsx +191 -0
  2806. package/.forge/worktrees/pipeline-ecd7cb0f/components/ClaudeTerminal.tsx +267 -0
  2807. package/.forge/worktrees/pipeline-ecd7cb0f/components/CodeViewer.tsx +787 -0
  2808. package/.forge/worktrees/pipeline-ecd7cb0f/components/ConversationEditor.tsx +411 -0
  2809. package/.forge/worktrees/pipeline-ecd7cb0f/components/ConversationGraphView.tsx +347 -0
  2810. package/.forge/worktrees/pipeline-ecd7cb0f/components/ConversationTerminalView.tsx +303 -0
  2811. package/.forge/worktrees/pipeline-ecd7cb0f/components/Dashboard.tsx +807 -0
  2812. package/.forge/worktrees/pipeline-ecd7cb0f/components/DashboardWrapper.tsx +9 -0
  2813. package/.forge/worktrees/pipeline-ecd7cb0f/components/DeliveryFlowEditor.tsx +491 -0
  2814. package/.forge/worktrees/pipeline-ecd7cb0f/components/DeliveryList.tsx +230 -0
  2815. package/.forge/worktrees/pipeline-ecd7cb0f/components/DeliveryWorkspace.tsx +589 -0
  2816. package/.forge/worktrees/pipeline-ecd7cb0f/components/DocTerminal.tsx +187 -0
  2817. package/.forge/worktrees/pipeline-ecd7cb0f/components/DocsViewer.tsx +574 -0
  2818. package/.forge/worktrees/pipeline-ecd7cb0f/components/HelpDialog.tsx +169 -0
  2819. package/.forge/worktrees/pipeline-ecd7cb0f/components/HelpTerminal.tsx +141 -0
  2820. package/.forge/worktrees/pipeline-ecd7cb0f/components/InlinePipelineView.tsx +111 -0
  2821. package/.forge/worktrees/pipeline-ecd7cb0f/components/LogViewer.tsx +194 -0
  2822. package/.forge/worktrees/pipeline-ecd7cb0f/components/MarkdownContent.tsx +73 -0
  2823. package/.forge/worktrees/pipeline-ecd7cb0f/components/MobileView.tsx +385 -0
  2824. package/.forge/worktrees/pipeline-ecd7cb0f/components/MonitorPanel.tsx +122 -0
  2825. package/.forge/worktrees/pipeline-ecd7cb0f/components/NewSessionModal.tsx +93 -0
  2826. package/.forge/worktrees/pipeline-ecd7cb0f/components/NewTaskModal.tsx +492 -0
  2827. package/.forge/worktrees/pipeline-ecd7cb0f/components/PipelineEditor.tsx +570 -0
  2828. package/.forge/worktrees/pipeline-ecd7cb0f/components/PipelineView.tsx +1018 -0
  2829. package/.forge/worktrees/pipeline-ecd7cb0f/components/PluginsPanel.tsx +472 -0
  2830. package/.forge/worktrees/pipeline-ecd7cb0f/components/ProjectDetail.tsx +1618 -0
  2831. package/.forge/worktrees/pipeline-ecd7cb0f/components/ProjectList.tsx +108 -0
  2832. package/.forge/worktrees/pipeline-ecd7cb0f/components/ProjectManager.tsx +401 -0
  2833. package/.forge/worktrees/pipeline-ecd7cb0f/components/SessionList.tsx +74 -0
  2834. package/.forge/worktrees/pipeline-ecd7cb0f/components/SessionView.tsx +726 -0
  2835. package/.forge/worktrees/pipeline-ecd7cb0f/components/SettingsModal.tsx +1647 -0
  2836. package/.forge/worktrees/pipeline-ecd7cb0f/components/SkillsPanel.tsx +969 -0
  2837. package/.forge/worktrees/pipeline-ecd7cb0f/components/StatusBar.tsx +99 -0
  2838. package/.forge/worktrees/pipeline-ecd7cb0f/components/TabBar.tsx +46 -0
  2839. package/.forge/worktrees/pipeline-ecd7cb0f/components/TaskBoard.tsx +113 -0
  2840. package/.forge/worktrees/pipeline-ecd7cb0f/components/TaskDetail.tsx +372 -0
  2841. package/.forge/worktrees/pipeline-ecd7cb0f/components/TerminalLauncher.tsx +398 -0
  2842. package/.forge/worktrees/pipeline-ecd7cb0f/components/TunnelToggle.tsx +206 -0
  2843. package/.forge/worktrees/pipeline-ecd7cb0f/components/UsagePanel.tsx +207 -0
  2844. package/.forge/worktrees/pipeline-ecd7cb0f/components/WebTerminal.tsx +1683 -0
  2845. package/.forge/worktrees/pipeline-ecd7cb0f/components/WorkspaceTree.tsx +221 -0
  2846. package/.forge/worktrees/pipeline-ecd7cb0f/components/WorkspaceView.tsx +4048 -0
  2847. package/.forge/worktrees/pipeline-ecd7cb0f/dev-test.sh +5 -0
  2848. package/.forge/worktrees/pipeline-ecd7cb0f/docs/Forge_Memory_Layer_Design.docx +0 -0
  2849. package/.forge/worktrees/pipeline-ecd7cb0f/docs/Forge_Strategy_Research_2026.docx +0 -0
  2850. package/.forge/worktrees/pipeline-ecd7cb0f/docs/LOCAL-DEPLOY.md +144 -0
  2851. package/.forge/worktrees/pipeline-ecd7cb0f/docs/roadmap-multi-agent-workflow.md +330 -0
  2852. package/.forge/worktrees/pipeline-ecd7cb0f/forge-logo.png +0 -0
  2853. package/.forge/worktrees/pipeline-ecd7cb0f/forge-logo.svg +106 -0
  2854. package/.forge/worktrees/pipeline-ecd7cb0f/hooks/useSidebarResize.ts +52 -0
  2855. package/.forge/worktrees/pipeline-ecd7cb0f/install.sh +29 -0
  2856. package/.forge/worktrees/pipeline-ecd7cb0f/instrumentation.ts +35 -0
  2857. package/.forge/worktrees/pipeline-ecd7cb0f/lib/agents/claude-adapter.ts +104 -0
  2858. package/.forge/worktrees/pipeline-ecd7cb0f/lib/agents/generic-adapter.ts +64 -0
  2859. package/.forge/worktrees/pipeline-ecd7cb0f/lib/agents/index.ts +245 -0
  2860. package/.forge/worktrees/pipeline-ecd7cb0f/lib/agents/types.ts +70 -0
  2861. package/.forge/worktrees/pipeline-ecd7cb0f/lib/artifacts.ts +106 -0
  2862. package/.forge/worktrees/pipeline-ecd7cb0f/lib/auth.ts +62 -0
  2863. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/docker.yaml +70 -0
  2864. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/http.yaml +66 -0
  2865. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/jenkins.yaml +92 -0
  2866. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/llm-vision.yaml +85 -0
  2867. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/playwright.yaml +111 -0
  2868. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/shell-command.yaml +60 -0
  2869. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/slack.yaml +48 -0
  2870. package/.forge/worktrees/pipeline-ecd7cb0f/lib/builtin-plugins/webhook.yaml +56 -0
  2871. package/.forge/worktrees/pipeline-ecd7cb0f/lib/claude-process.ts +352 -0
  2872. package/.forge/worktrees/pipeline-ecd7cb0f/lib/claude-sessions.ts +266 -0
  2873. package/.forge/worktrees/pipeline-ecd7cb0f/lib/claude-templates.ts +227 -0
  2874. package/.forge/worktrees/pipeline-ecd7cb0f/lib/cloudflared.ts +424 -0
  2875. package/.forge/worktrees/pipeline-ecd7cb0f/lib/crypto.ts +67 -0
  2876. package/.forge/worktrees/pipeline-ecd7cb0f/lib/delivery.ts +787 -0
  2877. package/.forge/worktrees/pipeline-ecd7cb0f/lib/dirs.ts +99 -0
  2878. package/.forge/worktrees/pipeline-ecd7cb0f/lib/flows.ts +86 -0
  2879. package/.forge/worktrees/pipeline-ecd7cb0f/lib/forge-mcp-server.ts +717 -0
  2880. package/.forge/worktrees/pipeline-ecd7cb0f/lib/forge-skills/forge-inbox.md +38 -0
  2881. package/.forge/worktrees/pipeline-ecd7cb0f/lib/forge-skills/forge-send.md +47 -0
  2882. package/.forge/worktrees/pipeline-ecd7cb0f/lib/forge-skills/forge-status.md +32 -0
  2883. package/.forge/worktrees/pipeline-ecd7cb0f/lib/forge-skills/forge-workspace-sync.md +37 -0
  2884. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/00-overview.md +40 -0
  2885. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/01-settings.md +194 -0
  2886. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/02-telegram.md +41 -0
  2887. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/03-tunnel.md +31 -0
  2888. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/04-tasks.md +52 -0
  2889. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/05-pipelines.md +460 -0
  2890. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/06-skills.md +43 -0
  2891. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/07-projects.md +73 -0
  2892. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/08-rules.md +53 -0
  2893. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/09-issue-autofix.md +55 -0
  2894. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/10-troubleshooting.md +89 -0
  2895. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/11-workspace.md +810 -0
  2896. package/.forge/worktrees/pipeline-ecd7cb0f/lib/help-docs/CLAUDE.md +62 -0
  2897. package/.forge/worktrees/pipeline-ecd7cb0f/lib/init.ts +266 -0
  2898. package/.forge/worktrees/pipeline-ecd7cb0f/lib/issue-scanner.ts +298 -0
  2899. package/.forge/worktrees/pipeline-ecd7cb0f/lib/logger.ts +79 -0
  2900. package/.forge/worktrees/pipeline-ecd7cb0f/lib/notifications.ts +75 -0
  2901. package/.forge/worktrees/pipeline-ecd7cb0f/lib/notify.ts +108 -0
  2902. package/.forge/worktrees/pipeline-ecd7cb0f/lib/password.ts +97 -0
  2903. package/.forge/worktrees/pipeline-ecd7cb0f/lib/pipeline-scheduler.ts +373 -0
  2904. package/.forge/worktrees/pipeline-ecd7cb0f/lib/pipeline.ts +1441 -0
  2905. package/.forge/worktrees/pipeline-ecd7cb0f/lib/plugins/executor.ts +347 -0
  2906. package/.forge/worktrees/pipeline-ecd7cb0f/lib/plugins/registry.ts +228 -0
  2907. package/.forge/worktrees/pipeline-ecd7cb0f/lib/plugins/types.ts +103 -0
  2908. package/.forge/worktrees/pipeline-ecd7cb0f/lib/project-sessions.ts +53 -0
  2909. package/.forge/worktrees/pipeline-ecd7cb0f/lib/projects.ts +86 -0
  2910. package/.forge/worktrees/pipeline-ecd7cb0f/lib/session-manager.ts +156 -0
  2911. package/.forge/worktrees/pipeline-ecd7cb0f/lib/session-utils.ts +53 -0
  2912. package/.forge/worktrees/pipeline-ecd7cb0f/lib/session-watcher.ts +345 -0
  2913. package/.forge/worktrees/pipeline-ecd7cb0f/lib/settings.ts +195 -0
  2914. package/.forge/worktrees/pipeline-ecd7cb0f/lib/skills.ts +458 -0
  2915. package/.forge/worktrees/pipeline-ecd7cb0f/lib/task-manager.ts +949 -0
  2916. package/.forge/worktrees/pipeline-ecd7cb0f/lib/telegram-bot.ts +1477 -0
  2917. package/.forge/worktrees/pipeline-ecd7cb0f/lib/telegram-standalone.ts +83 -0
  2918. package/.forge/worktrees/pipeline-ecd7cb0f/lib/terminal-server.ts +70 -0
  2919. package/.forge/worktrees/pipeline-ecd7cb0f/lib/terminal-standalone.ts +421 -0
  2920. package/.forge/worktrees/pipeline-ecd7cb0f/lib/usage-scanner.ts +249 -0
  2921. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/__tests__/state-machine.test.ts +388 -0
  2922. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/__tests__/workspace.test.ts +311 -0
  2923. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/agent-bus.ts +416 -0
  2924. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/agent-worker.ts +655 -0
  2925. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/backends/api-backend.ts +262 -0
  2926. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/backends/cli-backend.ts +491 -0
  2927. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/index.ts +82 -0
  2928. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/manager.ts +136 -0
  2929. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/orchestrator.ts +3400 -0
  2930. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/persistence.ts +309 -0
  2931. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/presets.ts +649 -0
  2932. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/requests.ts +287 -0
  2933. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/session-monitor.ts +240 -0
  2934. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/skill-installer.ts +275 -0
  2935. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/smith-memory.ts +498 -0
  2936. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/types.ts +241 -0
  2937. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace/watch-manager.ts +560 -0
  2938. package/.forge/worktrees/pipeline-ecd7cb0f/lib/workspace-standalone.ts +911 -0
  2939. package/.forge/worktrees/pipeline-ecd7cb0f/middleware.ts +51 -0
  2940. package/.forge/worktrees/pipeline-ecd7cb0f/next.config.ts +26 -0
  2941. package/.forge/worktrees/pipeline-ecd7cb0f/package.json +74 -0
  2942. package/.forge/worktrees/pipeline-ecd7cb0f/pnpm-lock.yaml +3719 -0
  2943. package/.forge/worktrees/pipeline-ecd7cb0f/pnpm-workspace.yaml +1 -0
  2944. package/.forge/worktrees/pipeline-ecd7cb0f/postcss.config.mjs +7 -0
  2945. package/.forge/worktrees/pipeline-ecd7cb0f/publish.sh +133 -0
  2946. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/README.md +66 -0
  2947. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/results/.gitignore +2 -0
  2948. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/run.ts +635 -0
  2949. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/01-text-utils/task.md +26 -0
  2950. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  2951. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  2952. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/02-pagination/task.md +48 -0
  2953. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  2954. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  2955. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  2956. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  2957. package/.forge/worktrees/pipeline-ecd7cb0f/scripts/verify-usage.ts +178 -0
  2958. package/.forge/worktrees/pipeline-ecd7cb0f/src/config/index.ts +129 -0
  2959. package/.forge/worktrees/pipeline-ecd7cb0f/src/core/db/database.ts +259 -0
  2960. package/.forge/worktrees/pipeline-ecd7cb0f/src/core/memory/strategy.ts +32 -0
  2961. package/.forge/worktrees/pipeline-ecd7cb0f/src/core/providers/chat.ts +65 -0
  2962. package/.forge/worktrees/pipeline-ecd7cb0f/src/core/providers/registry.ts +60 -0
  2963. package/.forge/worktrees/pipeline-ecd7cb0f/src/core/session/manager.ts +190 -0
  2964. package/.forge/worktrees/pipeline-ecd7cb0f/src/types/index.ts +129 -0
  2965. package/.forge/worktrees/pipeline-ecd7cb0f/start.sh +31 -0
  2966. package/.forge/worktrees/pipeline-ecd7cb0f/templates/smith-lead.json +45 -0
  2967. package/.forge/worktrees/pipeline-ecd7cb0f/tsconfig.json +42 -0
  2968. package/RELEASE_NOTES.md +13 -5
  2969. package/app/api/terminal-bell/route.ts +6 -2
  2970. package/app/api/workspace/[id]/stream/route.ts +3 -0
  2971. package/app/api/workspace/route.ts +20 -41
  2972. package/app/mobile/page.tsx +2 -1
  2973. package/app/page.tsx +2 -1
  2974. package/components/WebTerminal.tsx +62 -2
  2975. package/lib/claude-process.ts +14 -5
  2976. package/lib/forge-mcp-server.ts +20 -5
  2977. package/lib/help-docs/05-pipelines.md +44 -2
  2978. package/lib/pipeline.ts +181 -24
  2979. package/lib/task-manager.ts +5 -3
  2980. package/lib/terminal-standalone.ts +18 -1
  2981. package/lib/workspace/index.ts +3 -1
  2982. package/lib/workspace/manager.ts +1 -1
  2983. package/lib/workspace/orchestrator.ts +23 -8
  2984. package/lib/workspace-standalone.ts +67 -0
  2985. package/middleware.ts +2 -2
  2986. package/package.json +1 -1
  2987. package/start.sh +1 -0
@@ -0,0 +1,3400 @@
1
+ /**
2
+ * WorkspaceOrchestrator — manages a group of agents within a workspace.
3
+ *
4
+ * Responsibilities:
5
+ * - Create/remove agents
6
+ * - Run agents (auto-select backend, inject upstream context)
7
+ * - Listen to agent events → trigger downstream agents
8
+ * - Approval gating
9
+ * - Parallel execution (independent agents run concurrently)
10
+ * - Error recovery (restart from lastCheckpoint)
11
+ */
12
+
13
+ import { EventEmitter } from 'node:events';
14
+ import { readFileSync, existsSync, writeFileSync, unlinkSync, mkdirSync, statSync, readdirSync } from 'node:fs';
15
+ import { execSync } from 'node:child_process';
16
+ import { resolve, join } from 'node:path';
17
+ import { homedir } from 'node:os';
18
+ import type {
19
+ WorkspaceAgentConfig,
20
+ AgentState,
21
+ SmithStatus,
22
+ TaskStatus,
23
+ WorkerEvent,
24
+ BusMessage,
25
+ Artifact,
26
+ WorkspaceState,
27
+ DaemonWakeReason,
28
+ } from './types';
29
+ import { AgentWorker } from './agent-worker';
30
+ import { AgentBus } from './agent-bus';
31
+ import { WatchManager } from './watch-manager';
32
+ // ApiBackend loaded dynamically — its dependency chain uses @/src path aliases
33
+ // that only work in Next.js context, not in standalone tsx process
34
+ // import { ApiBackend } from './backends/api-backend';
35
+ import { CliBackend } from './backends/cli-backend';
36
+ import { appendAgentLog, saveWorkspace, saveWorkspaceSync, startAutoSave, stopAutoSave } from './persistence';
37
+ import { hasForgeSkills, installForgeSkills } from './skill-installer';
38
+ import {
39
+ loadMemory, saveMemory, createMemory, formatMemoryForPrompt,
40
+ addObservation, addSessionSummary, parseStepToObservations, buildSessionSummary,
41
+ } from './smith-memory';
42
+ import { getFixedSession } from '../project-sessions';
43
+
44
+ // ─── Workspace Topology Cache ────────────────────────────
45
+
46
+ export interface TopoAgent {
47
+ id: string;
48
+ label: string;
49
+ icon: string;
50
+ role: string; // full role text
51
+ roleSummary: string; // first line, ≤150 chars
52
+ primary: boolean;
53
+ dependsOn: string[]; // agent labels (not IDs)
54
+ dependsOnIds: string[];
55
+ workDir: string;
56
+ outputs: string[];
57
+ steps: string[]; // step labels
58
+ smithStatus: string;
59
+ taskStatus: string;
60
+ }
61
+
62
+ export interface WorkspaceTopo {
63
+ agents: TopoAgent[];
64
+ flow: string; // "Lead → Engineer → QA → Reviewer"
65
+ updatedAt: number;
66
+ }
67
+
68
+ // ─── Orchestrator Events ─────────────────────────────────
69
+
70
+ export type OrchestratorEvent =
71
+ | WorkerEvent
72
+ | { type: 'bus_message'; message: BusMessage }
73
+ | { type: 'approval_required'; agentId: string; upstreamId: string }
74
+ | { type: 'user_input_request'; agentId: string; fromAgent: string; question: string }
75
+ | { type: 'workspace_status'; running: number; done: number; total: number }
76
+ | { type: 'workspace_complete' }
77
+ | { type: 'watch_alert'; agentId: string; changes: any[]; summary: string; timestamp: number };
78
+
79
+ // ─── Orchestrator class ──────────────────────────────────
80
+
81
+ export class WorkspaceOrchestrator extends EventEmitter {
82
+ readonly workspaceId: string;
83
+ readonly projectPath: string;
84
+ readonly projectName: string;
85
+
86
+ private agents = new Map<string, { config: WorkspaceAgentConfig; worker: AgentWorker | null; state: AgentState }>();
87
+ private bus: AgentBus;
88
+ private watchManager: WatchManager;
89
+ private sessionMonitor: import('./session-monitor').SessionFileMonitor | null = null;
90
+ private approvalQueue = new Set<string>();
91
+ private daemonActive = false;
92
+ private createdAt = Date.now();
93
+ private healthCheckTimer: NodeJS.Timeout | null = null;
94
+ private settingsValidCache = new Map<string, number>(); // filePath → mtime (validated ok)
95
+ private agentRunningMsg = new Map<string, string>(); // agentId → messageId currently being processed
96
+ private reconcileTick = 0; // counts health check ticks for 60s reconcile
97
+ private _topoCache: WorkspaceTopo | null = null; // cached workspace topology
98
+ private roleInjectState = new Map<string, { lastInjectAt: number; msgsSinceInject: number }>(); // per-agent role reminder tracking
99
+
100
+ /** Emit a log event (auto-persisted via constructor listener) */
101
+ emitLog(agentId: string, entry: any): void {
102
+ this.emit('event', { type: 'log', agentId, entry } as any);
103
+ }
104
+
105
+ constructor(workspaceId: string, projectPath: string, projectName: string) {
106
+ super();
107
+ this.workspaceId = workspaceId;
108
+ this.projectPath = projectPath;
109
+ this.projectName = projectName;
110
+ this.bus = new AgentBus();
111
+ this.watchManager = new WatchManager(workspaceId, projectPath, () => this.agents as any);
112
+
113
+ // Auto-persist all log events to disk (so LogPanel can read them)
114
+ this.on('event', (event: any) => {
115
+ if (event.type === 'log' && event.agentId && event.entry) {
116
+ appendAgentLog(this.workspaceId, event.agentId, event.entry).catch(() => {});
117
+ }
118
+ });
119
+ // Handle watch events
120
+ this.watchManager.on('watch_alert', (event) => {
121
+ this.emit('event', event);
122
+ // Push alert to agent history so Log panel shows it
123
+ const alertEntry = this.agents.get(event.agentId);
124
+ if (alertEntry && event.entry) {
125
+ alertEntry.state.history.push(event.entry);
126
+ this.emit('event', { type: 'log', agentId: event.agentId, entry: event.entry } as any);
127
+ }
128
+ this.handleWatchAlert(event.agentId, event.summary);
129
+ });
130
+ // Note: watch_heartbeat (no changes) only logs to console, not to agent history/logs.jsonl
131
+
132
+ // Forward bus messages as orchestrator events (after dedup, skip ACKs)
133
+ this.bus.on('message', (msg: BusMessage) => {
134
+ if (msg.type === 'ack') return; // ACKs are internal, don't emit to UI
135
+ if (msg.to === '_system') {
136
+ this.emit('event', { type: 'bus_message', message: msg } satisfies OrchestratorEvent);
137
+ return;
138
+ }
139
+ this.handleBusMessage(msg);
140
+ });
141
+
142
+ // Start auto-save (every 10 seconds)
143
+ startAutoSave(workspaceId, () => this.getFullState());
144
+ }
145
+
146
+ // ─── Agent Management ──────────────────────────────────
147
+
148
+ /** Check if agent outputs or workDir conflict with existing agents */
149
+ private validateOutputs(config: WorkspaceAgentConfig, excludeId?: string): string | null {
150
+ if (config.type === 'input') return null;
151
+
152
+ const normalize = (p: string) => p.replace(/^\.?\//, '').replace(/\/$/, '') || '.';
153
+
154
+ // Validate workDir is within project (no ../ escape)
155
+ if (config.workDir) {
156
+ const relativeDir = config.workDir.replace(/^\.?\//, '');
157
+ if (relativeDir.includes('..')) {
158
+ return `Work directory "${config.workDir}" contains "..". Must be a subdirectory of the project.`;
159
+ }
160
+ const projectRoot = this.projectPath.endsWith('/') ? this.projectPath : this.projectPath + '/';
161
+ const resolved = resolve(this.projectPath, relativeDir);
162
+ if (resolved !== this.projectPath && !resolved.startsWith(projectRoot)) {
163
+ return `Work directory "${config.workDir}" is outside the project. Must be a subdirectory.`;
164
+ }
165
+ }
166
+
167
+ // Every non-input smith must have a unique workDir
168
+ const newDir = normalize(config.workDir || '.');
169
+
170
+ for (const [id, entry] of this.agents) {
171
+ if (id === excludeId || entry.config.type === 'input') continue;
172
+
173
+ const existingDir = normalize(entry.config.workDir || '.');
174
+
175
+ // Same workDir → conflict
176
+ if (newDir === existingDir) {
177
+ return `Work directory conflict: "${config.label}" and "${entry.config.label}" both use "${newDir === '.' ? 'project root' : newDir}/". Each smith must have a unique work directory.`;
178
+ }
179
+
180
+ // One is parent of the other → conflict (e.g., "src" and "src/components")
181
+ if (newDir.startsWith(existingDir + '/') || existingDir.startsWith(newDir + '/')) {
182
+ return `Work directory conflict: "${config.label}" (${newDir}/) overlaps with "${entry.config.label}" (${existingDir}/). Nested directories not allowed.`;
183
+ }
184
+
185
+ // Output path overlap is allowed — multiple agents can write to the same
186
+ // output directory (e.g., Engineer and UI Designer both output to src/).
187
+ // Work directory uniqueness already prevents file-level conflicts.
188
+ }
189
+ return null;
190
+ }
191
+
192
+ /** Check for non-blocking output overlaps — returns a warning message if any */
193
+ private getOutputWarnings(config: WorkspaceAgentConfig, excludeId?: string): string | null {
194
+ if (config.type === 'input' || !config.outputs?.length) return null;
195
+ const normalize = (p: string) => p.replace(/^\.?\//, '').replace(/\/$/, '') || '.';
196
+ const overlaps: string[] = [];
197
+ for (const [id, entry] of this.agents) {
198
+ if (id === excludeId || entry.config.type === 'input') continue;
199
+ for (const out of config.outputs) {
200
+ for (const existing of entry.config.outputs || []) {
201
+ if (normalize(out) === normalize(existing)) {
202
+ overlaps.push(`${entry.config.label} also outputs to "${out}"`);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ return overlaps.length ? `Output overlap (non-blocking): ${overlaps.join('; ')}` : null;
208
+ }
209
+
210
+ /** Detect if adding dependsOn edges would create a cycle in the DAG */
211
+ private detectCycle(agentId: string, dependsOn: string[]): string | null {
212
+ // Build adjacency: agent → agents it depends on
213
+ const deps = new Map<string, string[]>();
214
+ for (const [id, entry] of this.agents) {
215
+ if (id !== agentId) deps.set(id, [...entry.config.dependsOn]);
216
+ }
217
+ deps.set(agentId, [...dependsOn]);
218
+
219
+ // DFS cycle detection
220
+ const visited = new Set<string>();
221
+ const inStack = new Set<string>();
222
+
223
+ const dfs = (node: string): string | null => {
224
+ if (inStack.has(node)) return node; // cycle found
225
+ if (visited.has(node)) return null;
226
+ visited.add(node);
227
+ inStack.add(node);
228
+ for (const dep of deps.get(node) || []) {
229
+ const cycle = dfs(dep);
230
+ if (cycle) return cycle;
231
+ }
232
+ inStack.delete(node);
233
+ return null;
234
+ };
235
+
236
+ for (const id of deps.keys()) {
237
+ const cycle = dfs(id);
238
+ if (cycle) {
239
+ const cycleName = this.agents.get(cycle)?.config.label || cycle;
240
+ return `Circular dependency detected involving "${cycleName}". Dependencies must form a DAG (no cycles).`;
241
+ }
242
+ }
243
+ return null;
244
+ }
245
+
246
+ /** Check if agentA is upstream of agentB (A is in B's dependency chain) */
247
+ isUpstream(agentA: string, agentB: string): boolean {
248
+ const visited = new Set<string>();
249
+ const check = (current: string): boolean => {
250
+ if (current === agentA) return true;
251
+ if (visited.has(current)) return false;
252
+ visited.add(current);
253
+ const entry = this.agents.get(current);
254
+ if (!entry) return false;
255
+ return entry.config.dependsOn.some(dep => check(dep));
256
+ };
257
+ return check(agentB);
258
+ }
259
+
260
+ /** Get the primary agent for this workspace (if any) */
261
+ getPrimaryAgent(): { config: WorkspaceAgentConfig; state: AgentState } | null {
262
+ for (const [, entry] of this.agents) {
263
+ if (entry.config.primary) return entry;
264
+ }
265
+ return null;
266
+ }
267
+
268
+ addAgent(config: WorkspaceAgentConfig): void {
269
+ const conflict = this.validateOutputs(config);
270
+ if (conflict) throw new Error(conflict);
271
+ const warning = this.getOutputWarnings(config);
272
+ if (warning) console.warn(`[workspace] ${warning}`);
273
+
274
+ // Check DAG cycle before adding
275
+ const cycleErr = this.detectCycle(config.id, config.dependsOn);
276
+ if (cycleErr) throw new Error(cycleErr);
277
+
278
+ // Primary agent validation
279
+ this.validatePrimaryRules(config);
280
+
281
+ const state: AgentState = {
282
+ smithStatus: 'down',
283
+ taskStatus: 'idle',
284
+ history: [],
285
+ artifacts: [],
286
+ };
287
+ // Primary agent: force terminal-only, root dir
288
+ if (config.primary) {
289
+ config.persistentSession = true;
290
+ config.workDir = './';
291
+ }
292
+ this.agents.set(config.id, { config, worker: null, state });
293
+ // If daemon active, start persistent session + worker
294
+ if (this.daemonActive && config.type !== 'input' && config.persistentSession) {
295
+ this.enterDaemonListening(config.id);
296
+ const entry = this.agents.get(config.id)!;
297
+ entry.state.smithStatus = 'active';
298
+ this.ensurePersistentSession(config.id, config).then(() => {
299
+ this.startMessageLoop(config.id);
300
+ });
301
+ }
302
+ this.saveNow();
303
+ this.emitAgentsChanged();
304
+ }
305
+
306
+ removeAgent(id: string): void {
307
+ const entry = this.agents.get(id);
308
+ if (entry?.config.primary) throw new Error('Cannot remove the primary agent');
309
+ if (entry?.worker) {
310
+ entry.worker.stop();
311
+ }
312
+ this.agents.delete(id);
313
+ this.approvalQueue.delete(id);
314
+
315
+ // Clean up dangling dependsOn references in other agents
316
+ for (const [, other] of this.agents) {
317
+ const idx = other.config.dependsOn.indexOf(id);
318
+ if (idx !== -1) {
319
+ other.config.dependsOn.splice(idx, 1);
320
+ }
321
+ }
322
+
323
+ this.saveNow();
324
+ this.emitAgentsChanged();
325
+ }
326
+
327
+ /** Validate primary agent rules */
328
+ private validatePrimaryRules(config: WorkspaceAgentConfig, excludeId?: string): void {
329
+ if (config.primary) {
330
+ // Only one primary allowed
331
+ for (const [id, entry] of this.agents) {
332
+ if (id !== excludeId && entry.config.primary) {
333
+ throw new Error(`Only one primary agent allowed. "${entry.config.label}" is already primary.`);
334
+ }
335
+ }
336
+ }
337
+ // Non-primary agents cannot use root directory if a primary exists
338
+ if (!config.primary && config.type !== 'input') {
339
+ const workDir = config.workDir?.replace(/\/+$/, '') || '';
340
+ if (!workDir || workDir === '.' || workDir === './') {
341
+ const primary = this.getPrimaryAgent();
342
+ if (primary && primary.config.id !== excludeId) {
343
+ throw new Error(`Root directory is reserved for primary agent "${primary.config.label}". Choose a subdirectory.`);
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ updateAgentConfig(id: string, config: WorkspaceAgentConfig): void {
350
+ const entry = this.agents.get(id);
351
+ if (!entry) return;
352
+ // Validate agentId exists — fallback to default if deleted from Settings
353
+ if (config.agentId) {
354
+ try {
355
+ const { listAgents, getDefaultAgentId } = require('../agents/index');
356
+ const validAgents = new Set((listAgents() as any[]).map((a: any) => a.id));
357
+ if (!validAgents.has(config.agentId)) {
358
+ const fallback = getDefaultAgentId() || 'claude';
359
+ console.log(`[workspace] ${config.label}: agent "${config.agentId}" not found, falling back to "${fallback}"`);
360
+ config.agentId = fallback;
361
+ }
362
+ } catch {}
363
+ }
364
+ const conflict = this.validateOutputs(config, id);
365
+ if (conflict) throw new Error(conflict);
366
+ const warning = this.getOutputWarnings(config, id);
367
+ if (warning) console.warn(`[workspace] ${warning}`);
368
+ const cycleErr = this.detectCycle(id, config.dependsOn);
369
+ if (cycleErr) throw new Error(cycleErr);
370
+ this.validatePrimaryRules(config, id);
371
+ // Primary agent: force terminal-only, root dir
372
+ if (config.primary) {
373
+ config.persistentSession = true;
374
+ config.workDir = './';
375
+ }
376
+ if (entry.worker && entry.state.taskStatus === 'running') {
377
+ entry.worker.stop();
378
+ }
379
+
380
+ // If agent CLI changed (claude→codex, etc.), kill old terminal and clear bound session
381
+ const agentChanged = entry.config.agentId !== config.agentId;
382
+ if (agentChanged) {
383
+ console.log(`[workspace] ${config.label}: agent changed ${entry.config.agentId} → ${config.agentId}`);
384
+ if (entry.state.tmuxSession) {
385
+ try { execSync(`tmux kill-session -t "${entry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 }); } catch {}
386
+ console.log(`[workspace] ${config.label}: killed tmux session ${entry.state.tmuxSession}`);
387
+ }
388
+ entry.state.tmuxSession = undefined;
389
+ config.boundSessionId = undefined;
390
+ } else {
391
+ // Preserve server-managed fields the client doesn't track
392
+ if (!config.boundSessionId && entry.config.boundSessionId) {
393
+ config.boundSessionId = entry.config.boundSessionId;
394
+ }
395
+ }
396
+
397
+ entry.config = config;
398
+ // Reset status but keep history/artifacts (don't wipe logs)
399
+ entry.state.taskStatus = 'idle';
400
+ entry.state.error = undefined;
401
+ if (entry.worker) {
402
+ entry.worker.removeAllListeners();
403
+ entry.worker.stop();
404
+ }
405
+ entry.worker = null;
406
+
407
+ if (this.daemonActive) {
408
+ // Set 'starting' BEFORE creating worker — worker.executeDaemon emits 'active' synchronously
409
+ // which would cause a race: frontend sees active before boundSessionId is ready
410
+ entry.state.smithStatus = 'starting';
411
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'starting' } as any);
412
+ // Restart watch if config changed
413
+ this.watchManager.startWatch(id, config);
414
+ this.ensurePersistentSession(id, config).then(() => {
415
+ const e = this.agents.get(id);
416
+ if (e) {
417
+ // Rebuild worker + message loop AFTER session is ready (boundSessionId set)
418
+ this.enterDaemonListening(id);
419
+ e.state.smithStatus = 'active';
420
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'active' } as any);
421
+ this.emitAgentsChanged();
422
+ }
423
+ this.startMessageLoop(id);
424
+ });
425
+ }
426
+ this.saveNow();
427
+ this.emitAgentsChanged();
428
+ this.emit('event', { type: 'task_status', agentId: id, taskStatus: 'idle' } satisfies WorkerEvent);
429
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: entry.state.smithStatus } as any);
430
+ }
431
+
432
+ getAgentState(id: string): Readonly<AgentState> | undefined {
433
+ return this.agents.get(id)?.state;
434
+ }
435
+
436
+ getAllAgentStates(): Record<string, AgentState> {
437
+ const result: Record<string, AgentState> = {};
438
+ for (const [id, entry] of this.agents) {
439
+ const workerState = entry.worker?.getState();
440
+ // Merge: worker state for task/smith, entry.state for mode (orchestrator controls mode)
441
+ result[id] = workerState
442
+ ? { ...workerState, taskStatus: entry.state.taskStatus, tmuxSession: entry.state.tmuxSession, currentMessageId: entry.state.currentMessageId }
443
+ : entry.state;
444
+ }
445
+ return result;
446
+ }
447
+
448
+ // ─── Execution ─────────────────────────────────────────
449
+
450
+ /**
451
+ * Complete an Input node — set its content and mark as done.
452
+ * If re-submitted, resets downstream agents so they can re-run.
453
+ */
454
+ completeInput(agentId: string, content: string): void {
455
+ const entry = this.agents.get(agentId);
456
+ if (!entry || entry.config.type !== 'input') return;
457
+
458
+ const isUpdate = entry.state.taskStatus === 'done';
459
+
460
+ // Append to entries (incremental, not overwrite)
461
+ if (!entry.config.entries) entry.config.entries = [];
462
+ entry.config.entries.push({ content, timestamp: Date.now() });
463
+ // Keep bounded — max 100 entries, oldest removed
464
+ if (entry.config.entries.length > 100) {
465
+ entry.config.entries = entry.config.entries.slice(-100);
466
+ }
467
+ // Also set content to latest for backward compat
468
+ entry.config.content = content;
469
+
470
+ entry.state.taskStatus = 'done';
471
+ entry.state.completedAt = Date.now();
472
+ entry.state.artifacts = [{ type: 'text', summary: content.slice(0, 200) }];
473
+
474
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'done' } satisfies WorkerEvent);
475
+ this.emit('event', { type: 'done', agentId, summary: 'Input provided' } satisfies WorkerEvent);
476
+ this.emitAgentsChanged(); // push updated entries to frontend
477
+ this.bus.notifyTaskComplete(agentId, [], content.slice(0, 200));
478
+
479
+ // Send input_updated messages to downstream agents via bus
480
+ // routeMessageToAgent handles auto-execution for active smiths
481
+ for (const [id, downstream] of this.agents) {
482
+ if (downstream.config.type === 'input') continue;
483
+ if (!downstream.config.dependsOn.includes(agentId)) continue;
484
+ this.bus.send(agentId, id, 'notify', {
485
+ action: 'input_updated',
486
+ content: content.slice(0, 500),
487
+ });
488
+ console.log(`[bus] Input → ${downstream.config.label}: input_updated`);
489
+ }
490
+
491
+ this.saveNow();
492
+ }
493
+
494
+ /** Reset an agent and all its downstream to idle (for re-run) */
495
+ resetAgent(agentId: string): void {
496
+ const entry = this.agents.get(agentId);
497
+ if (!entry) return;
498
+ if (entry.worker) entry.worker.stop();
499
+ entry.worker = null;
500
+ // Kill orphaned tmux session if manual agent
501
+ if (entry.state.tmuxSession) {
502
+ try {
503
+ const { execSync } = require('node:child_process');
504
+ execSync(`tmux kill-session -t "${entry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 });
505
+ console.log(`[workspace] Killed tmux session ${entry.state.tmuxSession}`);
506
+ } catch {} // session might already be dead
507
+ }
508
+ entry.state = { smithStatus: 'down', taskStatus: 'idle', history: entry.state.history, artifacts: [] };
509
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'idle' } satisfies WorkerEvent);
510
+ this.emitAgentsChanged();
511
+ this.saveNow();
512
+ }
513
+
514
+ /** Reset all agents that depend on the given agent (recursively) */
515
+ private resetDownstream(agentId: string, visited = new Set<string>()): void {
516
+ if (visited.has(agentId)) return; // cycle protection
517
+ visited.add(agentId);
518
+
519
+ for (const [id, entry] of this.agents) {
520
+ if (id === agentId) continue;
521
+ if (!entry.config.dependsOn.includes(agentId)) continue;
522
+ if (entry.state.taskStatus === 'idle') continue;
523
+ console.log(`[workspace] Resetting ${entry.config.label} (${id}) to idle (upstream ${agentId} changed)`);
524
+ if (entry.worker) entry.worker.stop();
525
+ entry.worker = null;
526
+ entry.state = { smithStatus: entry.state.smithStatus, taskStatus: 'idle', history: entry.state.history, artifacts: [], cliSessionId: entry.state.cliSessionId };
527
+ this.emit('event', { type: 'task_status', agentId: id, taskStatus: 'idle' } satisfies WorkerEvent);
528
+ this.resetDownstream(id, visited);
529
+ }
530
+ }
531
+
532
+ /** Validate that an agent can run (sync check). Throws on error. */
533
+ validateCanRun(agentId: string): void {
534
+ const entry = this.agents.get(agentId);
535
+ if (!entry) throw new Error(`Agent "${agentId}" not found`);
536
+ if (entry.config.type === 'input') return;
537
+ if (entry.state.taskStatus === 'running') throw new Error(`Agent "${entry.config.label}" is already running`);
538
+ for (const depId of entry.config.dependsOn) {
539
+ const dep = this.agents.get(depId);
540
+ if (!dep) throw new Error(`Dependency "${depId}" not found (deleted?). Edit the agent to fix.`);
541
+ if (dep.state.taskStatus !== 'done') {
542
+ const hint = dep.state.taskStatus === 'idle' ? ' (never executed — run it first)'
543
+ : dep.state.taskStatus === 'failed' ? ' (failed — retry it first)'
544
+ : dep.state.taskStatus === 'running' ? ' (still running — wait for it to finish)'
545
+ : '';
546
+ throw new Error(`Dependency "${dep.config.label}" not completed yet${hint}`);
547
+ }
548
+ }
549
+ }
550
+
551
+ /** Run a specific agent. Requires daemon mode. force=true bypasses status checks (for retry). */
552
+ async runAgent(agentId: string, userInput?: string, force = false): Promise<void> {
553
+ if (!this.daemonActive) {
554
+ throw new Error('Start daemon first before running agents');
555
+ }
556
+ const label = this.agents.get(agentId)?.config.label || agentId;
557
+ console.log(`[workspace] runAgent(${label}, force=${force})`, new Error().stack?.split('\n').slice(2, 5).join(' <- '));
558
+ return this.runAgentDaemon(agentId, userInput, force);
559
+ }
560
+
561
+ /** @deprecated Use runAgent (which now delegates to daemon mode) */
562
+ private async runAgentLegacy(agentId: string, userInput?: string): Promise<void> {
563
+ const entry = this.agents.get(agentId);
564
+ if (!entry) throw new Error(`Agent "${agentId}" not found`);
565
+
566
+ // Input nodes are completed via completeInput(), not run
567
+ if (entry.config.type === 'input') {
568
+ if (userInput) this.completeInput(agentId, userInput);
569
+ return;
570
+ }
571
+
572
+ if (entry.state.taskStatus === 'running') return;
573
+
574
+ // Allow re-running done/failed/idle(was interrupted)/waiting_approval agents — reset them first
575
+ let resumeFromCheckpoint = false;
576
+ if (entry.state.taskStatus === 'done' || entry.state.taskStatus === 'failed' || entry.state.taskStatus === 'idle' || this.approvalQueue.has(agentId)) {
577
+ this.approvalQueue.delete(agentId);
578
+ console.log(`[workspace] Re-running ${entry.config.label} (was taskStatus=${entry.state.taskStatus})`);
579
+ // For failed: keep lastCheckpoint for resume
580
+ resumeFromCheckpoint = (entry.state.taskStatus === 'failed')
581
+ && entry.state.lastCheckpoint !== undefined;
582
+ if (entry.worker) entry.worker.stop();
583
+ entry.worker = null;
584
+ if (!resumeFromCheckpoint) {
585
+ entry.state = { smithStatus: entry.state.smithStatus, taskStatus: 'idle', history: entry.state.history, artifacts: [], cliSessionId: entry.state.cliSessionId };
586
+ } else {
587
+ entry.state.taskStatus = 'idle';
588
+ entry.state.error = undefined;
589
+ }
590
+ }
591
+
592
+ const { config } = entry;
593
+
594
+ // Check if all dependencies are done
595
+ for (const depId of config.dependsOn) {
596
+ const dep = this.agents.get(depId);
597
+ if (!dep || dep.state.taskStatus !== 'done') {
598
+ throw new Error(`Dependency "${dep?.config.label || depId}" not completed yet`);
599
+ }
600
+ }
601
+
602
+ // Build upstream context from dependencies (includes Input node content)
603
+ let upstreamContext = this.buildUpstreamContext(config);
604
+ if (userInput) {
605
+ const prefix = '## Additional Instructions:\n' + userInput;
606
+ upstreamContext = upstreamContext ? prefix + '\n\n---\n\n' + upstreamContext : prefix;
607
+ }
608
+
609
+ // Create backend
610
+ const backend = this.createBackend(config, agentId);
611
+
612
+ // Create worker with bus callbacks for inter-agent communication
613
+ // Load agent memory
614
+ const memory = loadMemory(this.workspaceId, agentId);
615
+ const memoryContext = formatMemoryForPrompt(memory);
616
+
617
+ const peerAgentIds = Array.from(this.agents.keys()).filter(id => id !== agentId);
618
+ const worker = new AgentWorker({
619
+ config,
620
+ backend,
621
+ projectPath: this.projectPath, workspaceId: this.workspaceId,
622
+ peerAgentIds,
623
+ memoryContext: memoryContext || undefined,
624
+ onBusSend: (to, content) => {
625
+ this.bus.send(agentId, to, 'notify', { action: 'agent_message', content });
626
+ },
627
+ onBusRequest: async (to, question) => {
628
+ const response = await this.bus.request(agentId, to, { action: 'question', content: question });
629
+ return response.payload.content || '(no response)';
630
+ },
631
+ onMemoryUpdate: (stepResults) => {
632
+ this.updateAgentMemory(agentId, config, stepResults);
633
+ },
634
+ });
635
+ entry.worker = worker;
636
+
637
+ // Forward worker events
638
+ worker.on('event', (event: WorkerEvent) => {
639
+ // Sync state
640
+ entry.state = worker.getState() as AgentState;
641
+
642
+ // Persist log entries to disk
643
+ if (event.type === 'log') {
644
+ appendAgentLog(this.workspaceId, agentId, event.entry).catch(() => {});
645
+ }
646
+
647
+ this.emit('event', event);
648
+
649
+ // Update liveness
650
+ if (event.type === 'task_status' || event.type === 'smith_status') {
651
+ this.updateAgentLiveness(agentId);
652
+ }
653
+
654
+ // On step complete → capture observation + notify bus
655
+ if (event.type === 'step') {
656
+ const step = config.steps[event.stepIndex];
657
+ if (step) {
658
+ this.bus.notifyStepComplete(agentId, step.label);
659
+
660
+ // Capture memory observation from the previous step's result
661
+ const prevStepIdx = event.stepIndex - 1;
662
+ if (prevStepIdx >= 0) {
663
+ const prevStep = config.steps[prevStepIdx];
664
+ const prevResult = entry.state.history
665
+ .filter(h => h.type === 'result' && h.subtype === 'step_complete')
666
+ .slice(-1)[0];
667
+ if (prevResult && prevStep) {
668
+ const obs = parseStepToObservations(prevStep.label, prevResult.content, entry.state.artifacts);
669
+ for (const o of obs) {
670
+ addObservation(this.workspaceId, agentId, config.label, config.role, o).catch(() => {});
671
+ }
672
+ }
673
+ }
674
+ }
675
+ }
676
+
677
+ // On done → notify + trigger downstream (or reply to sender if from downstream)
678
+ if (event.type === 'done') {
679
+ this.handleAgentDone(agentId, entry, event.summary);
680
+
681
+ this.emitWorkspaceStatus();
682
+ this.checkWorkspaceComplete();
683
+
684
+ // Note: no auto-rerun. Bus messages that need re-run go through user approval.
685
+ }
686
+
687
+ // On error → notify bus
688
+ if (event.type === 'error') {
689
+ this.bus.notifyError(agentId, event.error);
690
+ this.emitWorkspaceStatus();
691
+ }
692
+ });
693
+
694
+ // Inject only undelivered (pending) bus messages addressed to this agent
695
+ const pendingMsgs = this.bus.getPendingMessagesFor(agentId)
696
+ .filter(m => m.from !== agentId); // don't inject own messages
697
+ for (const msg of pendingMsgs) {
698
+ const fromLabel = this.agents.get(msg.from)?.config.label || msg.from;
699
+ worker.injectMessage({
700
+ type: 'system',
701
+ subtype: 'bus_message',
702
+ content: `[From ${fromLabel}]: ${msg.payload.content || msg.payload.action}`,
703
+ timestamp: new Date(msg.timestamp).toISOString(),
704
+ });
705
+ // Mark as delivered + ACK so sender knows it was received
706
+ msg.status = 'done';
707
+ }
708
+
709
+ // Start from checkpoint if recovering from failure
710
+ const startStep = resumeFromCheckpoint && entry.state.lastCheckpoint !== undefined
711
+ ? entry.state.lastCheckpoint + 1
712
+ : 0;
713
+
714
+ this.emitWorkspaceStatus();
715
+
716
+ // Execute (non-blocking — fire and forget, events handle the rest)
717
+ worker.execute(startStep, upstreamContext).catch(err => {
718
+ // Only set failed if worker didn't already handle it (avoid duplicate error events)
719
+ if (entry.state.taskStatus !== 'failed') {
720
+ entry.state.taskStatus = 'failed';
721
+ entry.state.error = err?.message || String(err);
722
+ this.emit('event', { type: 'error', agentId, error: entry.state.error! } satisfies WorkerEvent);
723
+ }
724
+ });
725
+ }
726
+
727
+ /** Run all agents — starts daemon if not active, then runs all ready agents */
728
+ async runAll(): Promise<void> {
729
+ if (!this.daemonActive) {
730
+ return this.startDaemon();
731
+ }
732
+ const ready = this.getDaemonReadyAgents();
733
+ await Promise.all(ready.map(id => this.runAgentDaemon(id)));
734
+ }
735
+
736
+ /** Run a single agent in daemon mode. force=true resets failed/interrupted agents. triggerMessageId tracks which bus message started this. */
737
+ async runAgentDaemon(agentId: string, userInput?: string, force = false, triggerMessageId?: string): Promise<void> {
738
+ const entry = this.agents.get(agentId);
739
+ if (!entry) throw new Error(`Agent "${agentId}" not found`);
740
+
741
+ if (entry.config.type === 'input') {
742
+ if (userInput) this.completeInput(agentId, userInput);
743
+ return;
744
+ }
745
+
746
+ if (entry.state.taskStatus === 'running' && !force) return;
747
+ // Already has a daemon worker running → skip (unless force retry)
748
+ if (entry.worker && entry.state.smithStatus === 'active' && !force) return;
749
+
750
+ // Already done → enter daemon listening directly (don't re-run steps)
751
+ if (entry.state.taskStatus === 'done' && !force) {
752
+ return this.enterDaemonListening(agentId);
753
+ }
754
+
755
+ if (!force) {
756
+ // Failed → leave as-is, user must retry explicitly
757
+ if (entry.state.taskStatus === 'failed') return;
758
+ // waiting_approval → leave as-is
759
+ if (this.approvalQueue.has(agentId)) return;
760
+ }
761
+
762
+ // Reset state for fresh start — preserve smithStatus and mode
763
+ if (entry.state.taskStatus !== 'idle') {
764
+ this.approvalQueue.delete(agentId);
765
+ if (entry.worker) entry.worker.stop();
766
+ entry.worker = null;
767
+ entry.state = {
768
+ smithStatus: entry.state.smithStatus,
769
+ taskStatus: 'idle',
770
+ history: [],
771
+ artifacts: [],
772
+ cliSessionId: entry.state.cliSessionId, // preserve session for --resume
773
+ };
774
+ }
775
+
776
+ // Ensure smith is active when daemon starts this agent
777
+ // Skip if 'starting': ensurePersistentSession is in progress and will set 'active' when done.
778
+ if (this.daemonActive && entry.state.smithStatus !== 'active' && entry.state.smithStatus !== 'starting') {
779
+ entry.state.smithStatus = 'active';
780
+ this.emit('event', { type: 'smith_status', agentId, smithStatus: 'active' } satisfies WorkerEvent);
781
+ }
782
+
783
+ const { config } = entry;
784
+
785
+ // Check dependencies
786
+ for (const depId of config.dependsOn) {
787
+ const dep = this.agents.get(depId);
788
+ if (!dep) throw new Error(`Dependency "${depId}" not found`);
789
+ if (force) {
790
+ // Manual trigger: only require upstream smith to be active (online)
791
+ if (dep.config.type !== 'input' && dep.state.smithStatus !== 'active') {
792
+ throw new Error(`Dependency "${dep.config.label}" smith is not active — start daemon first`);
793
+ }
794
+ } else {
795
+ // Auto trigger: require upstream task completed
796
+ if (dep.state.taskStatus !== 'done') {
797
+ throw new Error(`Dependency "${dep.config.label}" not completed yet`);
798
+ }
799
+ }
800
+ }
801
+
802
+ // Role is now injected via buildUpstreamContext (headless) and persistent session preamble (terminal).
803
+ // No longer writes to CLAUDE.md — project files stay clean when daemon stops.
804
+
805
+ let upstreamContext = this.buildUpstreamContext(config);
806
+ if (userInput) {
807
+ const prefix = '## Additional Instructions:\n' + userInput;
808
+ upstreamContext = upstreamContext ? prefix + '\n\n---\n\n' + upstreamContext : prefix;
809
+ }
810
+
811
+ const backend = this.createBackend(config, agentId);
812
+ const memory = loadMemory(this.workspaceId, agentId);
813
+ const memoryContext = formatMemoryForPrompt(memory);
814
+ const peerAgentIds = Array.from(this.agents.keys()).filter(id => id !== agentId);
815
+
816
+ const worker = new AgentWorker({
817
+ config, backend,
818
+ projectPath: this.projectPath, workspaceId: this.workspaceId,
819
+ peerAgentIds,
820
+ memoryContext: memoryContext || undefined,
821
+ onBusSend: (to, content) => {
822
+ this.bus.send(agentId, to, 'notify', { action: 'agent_message', content });
823
+ },
824
+ onBusRequest: async (to, question) => {
825
+ const response = await this.bus.request(agentId, to, { action: 'question', content: question });
826
+ return response.payload.content || '(no response)';
827
+ },
828
+ onMessageDone: (messageId) => {
829
+ const busMsg = this.bus.getLog().find(m => m.id === messageId);
830
+ if (busMsg) {
831
+ busMsg.status = 'done';
832
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'done' } as any);
833
+ this.emitAgentsChanged();
834
+ }
835
+ },
836
+ onMessageFailed: (messageId) => {
837
+ const busMsg = this.bus.getLog().find(m => m.id === messageId);
838
+ if (busMsg) {
839
+ busMsg.status = 'failed';
840
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'failed' } as any);
841
+ this.emitAgentsChanged();
842
+ }
843
+ },
844
+ onMemoryUpdate: (stepResults) => {
845
+ try {
846
+ const observations = stepResults.flatMap((r, i) =>
847
+ parseStepToObservations(config.steps[i]?.label || `Step ${i}`, r, entry.state.artifacts)
848
+ );
849
+ for (const obs of observations) addObservation(this.workspaceId, agentId, config.label, config.role, obs);
850
+ const stepLabels = config.steps.map(s => s.label);
851
+ const summary = buildSessionSummary(stepLabels, stepResults, entry.state.artifacts);
852
+ addSessionSummary(this.workspaceId, agentId, summary);
853
+ } catch {}
854
+ },
855
+ });
856
+
857
+ entry.worker = worker;
858
+
859
+ // Track trigger message so smith can mark it done/failed on completion
860
+ if (triggerMessageId) {
861
+ worker.setProcessingMessage(triggerMessageId);
862
+ }
863
+
864
+ // Forward events (same as runAgent)
865
+ worker.on('event', (event: WorkerEvent) => {
866
+ if (event.type === 'task_status') {
867
+ entry.state.taskStatus = event.taskStatus;
868
+ entry.state.error = event.error;
869
+ if (event.taskStatus === 'running') entry.state.startedAt = Date.now();
870
+ const workerState = worker.getState();
871
+ entry.state.daemonIteration = workerState.daemonIteration;
872
+ }
873
+ if (event.type === 'smith_status') {
874
+ entry.state.smithStatus = event.smithStatus;
875
+ }
876
+ if (event.type === 'log') {
877
+ appendAgentLog(this.workspaceId, agentId, event.entry).catch(() => {});
878
+ }
879
+ this.emit('event', event);
880
+ if (event.type === 'task_status' || event.type === 'smith_status') {
881
+ this.updateAgentLiveness(agentId);
882
+ }
883
+ if (event.type === 'step' && event.stepIndex >= 0) {
884
+ const step = config.steps[event.stepIndex];
885
+ if (step) this.bus.notifyStepComplete(agentId, step.label);
886
+ }
887
+ if (event.type === 'done') {
888
+ this.handleAgentDone(agentId, entry, event.summary);
889
+ }
890
+ if (event.type === 'error') {
891
+ this.agentRunningMsg.delete(agentId);
892
+ this.bus.notifyError(agentId, event.error);
893
+ this.emitWorkspaceStatus();
894
+ }
895
+ });
896
+
897
+ // Inject pending messages
898
+ const pendingMsgs = this.bus.getPendingMessagesFor(agentId)
899
+ .filter(m => m.from !== agentId);
900
+ for (const msg of pendingMsgs) {
901
+ const fromLabel = this.agents.get(msg.from)?.config.label || msg.from;
902
+ worker.injectMessage({
903
+ type: 'system', subtype: 'bus_message',
904
+ content: `[From ${fromLabel}]: ${msg.payload.content || msg.payload.action}`,
905
+ timestamp: new Date(msg.timestamp).toISOString(),
906
+ });
907
+ msg.status = 'done';
908
+ }
909
+
910
+ this.emitWorkspaceStatus();
911
+
912
+ // Execute in daemon mode (non-blocking)
913
+ worker.executeDaemon(0, upstreamContext).catch(err => {
914
+ if (entry.state.taskStatus !== 'failed') {
915
+ this.agentRunningMsg.delete(agentId);
916
+ entry.state.taskStatus = 'failed';
917
+ entry.state.error = err?.message || String(err);
918
+ this.emit('event', { type: 'error', agentId, error: entry.state.error! } satisfies WorkerEvent);
919
+ }
920
+ });
921
+ }
922
+
923
+ /** Start all agents in daemon mode — orchestrator manages each smith's lifecycle */
924
+ async startDaemon(): Promise<void> {
925
+ if (this.daemonActive) return;
926
+ this.daemonActive = true;
927
+ console.log(`[workspace] Starting daemon mode...`);
928
+
929
+ // Clean up stale state from previous run
930
+ this.bus.markAllRunningAsFailed();
931
+
932
+ // Install forge skills globally (once per daemon start)
933
+ try {
934
+ installForgeSkills(this.projectPath, this.workspaceId, '', Number(process.env.PORT) || 8403);
935
+ } catch {}
936
+
937
+ // Validate agent IDs — fallback to default if configured agent was deleted from Settings
938
+ let defaultAgentId = 'claude';
939
+ try {
940
+ const { listAgents, getDefaultAgentId } = await import('../agents/index') as any;
941
+ const validAgents = new Set((listAgents() as any[]).map(a => a.id));
942
+ defaultAgentId = getDefaultAgentId() || 'claude';
943
+ for (const [id, entry] of this.agents) {
944
+ if (entry.config.type === 'input') continue;
945
+ if (entry.config.agentId && !validAgents.has(entry.config.agentId)) {
946
+ console.log(`[daemon] ${entry.config.label}: agent "${entry.config.agentId}" not found, falling back to "${defaultAgentId}"`);
947
+ entry.config.agentId = defaultAgentId;
948
+ this.emit('event', { type: 'log', agentId: id, entry: { type: 'system', subtype: 'warning', content: `Agent "${entry.config.agentId}" not found in Settings — using default "${defaultAgentId}"`, timestamp: new Date().toISOString() } } as any);
949
+ this.saveNow();
950
+ }
951
+ }
952
+ } catch {}
953
+
954
+ // Start each smith one by one, verify each starts correctly
955
+ let started = 0;
956
+ let failed = 0;
957
+ for (const [id, entry] of this.agents) {
958
+ if (entry.config.type === 'input') continue;
959
+
960
+ // Kill any stale worker from previous run
961
+ if (entry.worker) {
962
+ entry.worker.stop();
963
+ entry.worker = null;
964
+ }
965
+
966
+ // Stop any existing message loop
967
+ this.stopMessageLoop(id);
968
+
969
+ try {
970
+ // 1. Start daemon listening loop (creates worker)
971
+ this.enterDaemonListening(id);
972
+
973
+ // 2. Verify worker was created
974
+ if (!entry.worker) {
975
+ throw new Error('Worker not created');
976
+ }
977
+
978
+ // 3. Set smith status — persistent session agents stay 'starting' until ensurePersistentSession completes
979
+ entry.state.smithStatus = entry.config.persistentSession ? 'starting' : 'active';
980
+ entry.state.error = undefined;
981
+
982
+ // 4. Start message loop (delayed for persistent session agents — session must exist first)
983
+ if (!entry.config.persistentSession) {
984
+ this.startMessageLoop(id);
985
+ }
986
+
987
+ // 5. Update liveness for bus routing
988
+ this.updateAgentLiveness(id);
989
+
990
+ // 6. Notify frontend
991
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: entry.state.smithStatus } as any);
992
+
993
+ started++;
994
+ console.log(`[daemon] ✓ ${entry.config.label}: ${entry.state.smithStatus} (task=${entry.state.taskStatus})`);
995
+ } catch (err: any) {
996
+ entry.state.smithStatus = 'down';
997
+ entry.state.error = `Failed to start: ${err.message}`;
998
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'down' } satisfies WorkerEvent);
999
+ failed++;
1000
+ console.error(`[daemon] ✗ ${entry.config.label}: failed — ${err.message}`);
1001
+ }
1002
+ }
1003
+
1004
+ // Migration: clean any legacy Forge blocks from CLAUDE.md files (role/topo no longer written to disk)
1005
+ this.cleanLegacyClaudeMdBlocks();
1006
+
1007
+ // Create persistent terminal sessions, then start their message loops
1008
+ for (const [id, entry] of this.agents) {
1009
+ if (entry.config.type === 'input' || !entry.config.persistentSession) continue;
1010
+ await this.ensurePersistentSession(id, entry.config);
1011
+ // Set active now that session + boundSessionId are ready
1012
+ if (entry.state.smithStatus === 'starting') {
1013
+ entry.state.smithStatus = 'active';
1014
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'active' } as any);
1015
+ }
1016
+ if (entry.state.smithStatus === 'active') {
1017
+ // Inject role preamble so Claude knows its role (replaces CLAUDE.md writing)
1018
+ if (entry.config.role?.trim()) {
1019
+ const preamble = this.buildRolePreamble(entry.config);
1020
+ if (this.injectIntoSession(id, preamble)) {
1021
+ this.markRoleInjected(id);
1022
+ console.log(`[daemon] ${entry.config.label}: injected role preamble`);
1023
+ }
1024
+ }
1025
+ this.startMessageLoop(id);
1026
+ } else {
1027
+ console.log(`[daemon] ${entry.config.label}: skipped message loop (smith=${entry.state.smithStatus})`);
1028
+ }
1029
+ }
1030
+
1031
+ // Build workspace topology cache (all smiths can query via MCP get_agents)
1032
+ this.rebuildTopo();
1033
+
1034
+ // Start watch loops for agents with watch config
1035
+ this.watchManager.start();
1036
+
1037
+ // Start session file monitors for agents with known session IDs
1038
+ this.startSessionMonitors().catch(err => console.error('[session-monitor] Failed to start:', err.message));
1039
+
1040
+ // Start health check — monitor all agents every 10s, auto-heal
1041
+ this.startHealthCheck();
1042
+
1043
+ console.log(`[workspace] Daemon started: ${started} smiths active, ${failed} failed`);
1044
+ this.emitAgentsChanged();
1045
+ }
1046
+
1047
+ /** Get agents that can start in daemon mode (idle, done — with deps met) */
1048
+ private getDaemonReadyAgents(): string[] {
1049
+ const ready: string[] = [];
1050
+ for (const [id, entry] of this.agents) {
1051
+ if (entry.config.type === 'input') continue;
1052
+ if (entry.state.taskStatus === 'running' || entry.state.smithStatus === 'active') {
1053
+ console.log(`[daemon] ${entry.config.label}: already smithStatus=${entry.state.smithStatus} taskStatus=${entry.state.taskStatus}`);
1054
+ continue;
1055
+ }
1056
+ const allDepsDone = entry.config.dependsOn.every(depId => {
1057
+ const dep = this.agents.get(depId);
1058
+ return dep && (dep.state.taskStatus === 'done');
1059
+ });
1060
+ if (allDepsDone) {
1061
+ console.log(`[daemon] ${entry.config.label}: ready (taskStatus=${entry.state.taskStatus})`);
1062
+ ready.push(id);
1063
+ } else {
1064
+ const unmet = entry.config.dependsOn.filter(d => {
1065
+ const dep = this.agents.get(d);
1066
+ return !dep || (dep.state.taskStatus !== 'done');
1067
+ }).map(d => this.agents.get(d)?.config.label || d);
1068
+ console.log(`[daemon] ${entry.config.label}: not ready — deps unmet: ${unmet.join(', ')} (taskStatus=${entry.state.taskStatus})`);
1069
+ }
1070
+ }
1071
+ return ready;
1072
+ }
1073
+
1074
+ /** Put a done agent into daemon listening mode without re-running steps */
1075
+ private enterDaemonListening(agentId: string): void {
1076
+ const entry = this.agents.get(agentId);
1077
+ if (!entry) return;
1078
+
1079
+ // Stop existing worker first to prevent duplicate execution
1080
+ if (entry.worker) {
1081
+ entry.worker.removeAllListeners();
1082
+ entry.worker.stop();
1083
+ entry.worker = null;
1084
+ }
1085
+
1086
+ const { config } = entry;
1087
+
1088
+ const backend = this.createBackend(config, agentId);
1089
+ const peerAgentIds = Array.from(this.agents.keys()).filter(id => id !== agentId);
1090
+
1091
+ const worker = new AgentWorker({
1092
+ config, backend,
1093
+ projectPath: this.projectPath, workspaceId: this.workspaceId,
1094
+ peerAgentIds,
1095
+ initialTaskStatus: entry.state.taskStatus, // preserve current task status
1096
+ onBusSend: (to, content) => {
1097
+ this.bus.send(agentId, to, 'notify', { action: 'agent_message', content });
1098
+ },
1099
+ onBusRequest: async (to, question) => {
1100
+ const response = await this.bus.request(agentId, to, { action: 'question', content: question });
1101
+ return response.payload.content || '(no response)';
1102
+ },
1103
+ onMessageDone: (messageId) => {
1104
+ const busMsg = this.bus.getLog().find(m => m.id === messageId);
1105
+ if (busMsg) {
1106
+ busMsg.status = 'done';
1107
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'done' } as any);
1108
+ this.emitAgentsChanged();
1109
+ }
1110
+ },
1111
+ onMessageFailed: (messageId) => {
1112
+ const busMsg = this.bus.getLog().find(m => m.id === messageId);
1113
+ if (busMsg) {
1114
+ busMsg.status = 'failed';
1115
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'failed' } as any);
1116
+ this.emitAgentsChanged();
1117
+ }
1118
+ },
1119
+ });
1120
+
1121
+ entry.worker = worker;
1122
+
1123
+ // Forward events (same handler as runAgentDaemon)
1124
+ worker.on('event', (event: WorkerEvent) => {
1125
+ if (event.type === 'task_status') {
1126
+ entry.state.taskStatus = event.taskStatus;
1127
+ entry.state.error = event.error;
1128
+ const workerState = worker.getState();
1129
+ entry.state.daemonIteration = workerState.daemonIteration;
1130
+ }
1131
+ if (event.type === 'smith_status') {
1132
+ entry.state.smithStatus = event.smithStatus;
1133
+ }
1134
+ if (event.type === 'log') {
1135
+ appendAgentLog(this.workspaceId, agentId, event.entry).catch(() => {});
1136
+ }
1137
+ this.emit('event', event);
1138
+ if (event.type === 'task_status' || event.type === 'smith_status') {
1139
+ this.updateAgentLiveness(agentId);
1140
+ }
1141
+ if (event.type === 'done') {
1142
+ this.handleAgentDone(agentId, entry, event.summary);
1143
+ }
1144
+ if (event.type === 'error') {
1145
+ this.agentRunningMsg.delete(agentId);
1146
+ this.bus.notifyError(agentId, event.error);
1147
+ }
1148
+ });
1149
+
1150
+ // Message loop (startMessageLoop) handles auto-consumption of pending messages
1151
+
1152
+ console.log(`[workspace] Agent "${config.label}" entering daemon listening (task=${entry.state.taskStatus})`);
1153
+
1154
+ // executeDaemon with skipSteps=true → goes directly to listening loop
1155
+ worker.executeDaemon(0, undefined, true).catch(err => {
1156
+ console.error(`[workspace] enterDaemonListening error for ${config.label}:`, err.message);
1157
+ });
1158
+ }
1159
+
1160
+ /** Stop all agents (exit daemon mode) */
1161
+ /** Stop all agents — orchestrator shuts down each smith */
1162
+ stopDaemon(): void {
1163
+ this.daemonActive = false;
1164
+ console.log('[workspace] Stopping daemon...');
1165
+
1166
+ for (const [id, entry] of this.agents) {
1167
+ if (entry.config.type === 'input') continue;
1168
+
1169
+ // 1. Stop message loop
1170
+ this.stopMessageLoop(id);
1171
+
1172
+ // 2. Stop worker
1173
+ if (entry.worker) {
1174
+ entry.worker.stop();
1175
+ entry.worker = null;
1176
+ }
1177
+
1178
+ // 2b. For persistent sessions: send /clear to reset Claude's context if user is attached.
1179
+ // This is a Claude Code slash command — no LLM call, just a local context reset.
1180
+ if (entry.state.tmuxSession && entry.config.role?.trim()) {
1181
+ let isAttached = false;
1182
+ try {
1183
+ const info = execSync(`tmux display-message -t "${entry.state.tmuxSession}" -p "#{session_attached}" 2>/dev/null`, { timeout: 3000, encoding: 'utf-8' }).trim();
1184
+ isAttached = info !== '0';
1185
+ } catch {}
1186
+ if (isAttached) {
1187
+ try { this.injectIntoSession(id, '/clear'); } catch {}
1188
+ }
1189
+ }
1190
+ this.roleInjectState.delete(id);
1191
+
1192
+ // 3. Kill tmux session (skip if user is attached to it)
1193
+ if (entry.state.tmuxSession) {
1194
+ let isAttached = false;
1195
+ try {
1196
+ const info = execSync(`tmux display-message -t "${entry.state.tmuxSession}" -p "#{session_attached}" 2>/dev/null`, { timeout: 3000, encoding: 'utf-8' }).trim();
1197
+ isAttached = info !== '0';
1198
+ } catch {}
1199
+ if (isAttached) {
1200
+ console.log(`[daemon] ${entry.config.label}: tmux session attached by user, not killing`);
1201
+ } else {
1202
+ try { execSync(`tmux kill-session -t "${entry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 }); } catch {}
1203
+ }
1204
+ entry.state.tmuxSession = undefined;
1205
+ }
1206
+
1207
+ // 4. Set smith down, reset running tasks
1208
+ entry.state.smithStatus = 'down';
1209
+ if (entry.state.taskStatus === 'running') {
1210
+ entry.state.taskStatus = 'idle';
1211
+ }
1212
+ entry.state.error = undefined;
1213
+ this.updateAgentLiveness(id);
1214
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'down' } satisfies WorkerEvent);
1215
+
1216
+ console.log(`[daemon] ■ ${entry.config.label}: stopped`);
1217
+ }
1218
+
1219
+ // Mark running messages as failed
1220
+ this.bus.markAllRunningAsFailed();
1221
+ this.emitAgentsChanged();
1222
+ this.watchManager.stop();
1223
+ this.stopAllTerminalMonitors();
1224
+ if (this.sessionMonitor) { this.sessionMonitor.stopAll(); this.sessionMonitor = null; }
1225
+ this.stopHealthCheck();
1226
+ this.forgeActedMessages.clear();
1227
+ this.busMarkerScanned.clear();
1228
+ this.forgeAgentStartTime = 0;
1229
+ this.agentRunningMsg.clear();
1230
+ this.reconcileTick = 0;
1231
+ console.log('[workspace] Daemon stopped');
1232
+ }
1233
+
1234
+ // ─── Hook-based completion ─────────────────────────────
1235
+
1236
+ /** Called by Claude Code Stop hook via HTTP — agent finished a turn */
1237
+ handleHookDone(agentId: string): void {
1238
+ const entry = this.agents.get(agentId);
1239
+ if (!entry) return;
1240
+ if (!this.daemonActive) return;
1241
+
1242
+ console.log(`[hook] ${entry.config.label}: Stop hook → done (was ${entry.state.taskStatus})`);
1243
+ entry.state.taskStatus = 'done';
1244
+ entry.state.completedAt = Date.now();
1245
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'done' } as any);
1246
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'hook_done', content: 'Claude Code Stop hook: turn completed', timestamp: new Date().toISOString() } } as any);
1247
+ this.handleAgentDone(agentId, entry, 'Stop hook');
1248
+ this.sessionMonitor?.resetState(agentId);
1249
+ this.saveNow();
1250
+ this.emitAgentsChanged();
1251
+ }
1252
+
1253
+ // ─── Session File Monitor ──────────────────────────────
1254
+
1255
+ private async startSessionMonitors(): Promise<void> {
1256
+ console.log('[session-monitor] Initializing...');
1257
+ const { SessionFileMonitor } = await import('./session-monitor');
1258
+ this.sessionMonitor = new SessionFileMonitor();
1259
+
1260
+ // Listen for state changes from session file monitor
1261
+ this.sessionMonitor.on('stateChange', (event: any) => {
1262
+ const entry = this.agents.get(event.agentId);
1263
+ if (!entry) {
1264
+ console.log(`[session-monitor] stateChange: agent ${event.agentId} not found in map`);
1265
+ return;
1266
+ }
1267
+ console.log(`[session-monitor] stateChange: ${entry.config.label} ${event.state} (current taskStatus=${entry.state.taskStatus})`);
1268
+
1269
+ if (event.state === 'running' && entry.state.taskStatus !== 'running') {
1270
+ entry.state.taskStatus = 'running';
1271
+ console.log(`[session-monitor] → emitting task_status=running for ${entry.config.label}`);
1272
+ this.emit('event', { type: 'task_status', agentId: event.agentId, taskStatus: 'running' } as any);
1273
+ this.emitAgentsChanged();
1274
+ }
1275
+
1276
+ if (event.state === 'done' && entry.state.taskStatus === 'running') {
1277
+ entry.state.taskStatus = 'done';
1278
+ this.emit('event', { type: 'task_status', agentId: event.agentId, taskStatus: 'done' } as any);
1279
+ console.log(`[session-monitor] ${event.agentId}: done — ${event.detail || 'turn completed'}`);
1280
+ this.handleAgentDone(event.agentId, entry, event.detail);
1281
+ this.emitAgentsChanged();
1282
+ }
1283
+ });
1284
+
1285
+ // Start monitors for all agents with known session IDs
1286
+ for (const [id, entry] of this.agents) {
1287
+ if (entry.config.type === 'input') continue;
1288
+ await this.startAgentSessionMonitor(id, entry.config);
1289
+ }
1290
+ }
1291
+
1292
+ private async startAgentSessionMonitor(agentId: string, config: WorkspaceAgentConfig): Promise<void> {
1293
+ if (!this.sessionMonitor) return;
1294
+
1295
+ // Determine session file path
1296
+ let sessionId: string | undefined;
1297
+
1298
+ if (config.primary) {
1299
+ sessionId = getFixedSession(this.projectPath);
1300
+ console.log(`[session-monitor] ${config.label}: primary fixedSession=${sessionId || 'NONE'}`);
1301
+ } else {
1302
+ sessionId = config.boundSessionId;
1303
+ console.log(`[session-monitor] ${config.label}: boundSession=${sessionId || 'NONE'}`);
1304
+ }
1305
+
1306
+ if (!sessionId) {
1307
+ // Try to auto-bind from session files on disk
1308
+ sessionId = this.getLatestSessionId(config.workDir);
1309
+ if (sessionId && !config.primary) {
1310
+ config.boundSessionId = sessionId;
1311
+ this.saveNow();
1312
+ console.log(`[session-monitor] ${config.label}: auto-bound to ${sessionId}`);
1313
+ }
1314
+ if (!sessionId) {
1315
+ console.log(`[session-monitor] ${config.label}: no sessionId, skipping`);
1316
+ return;
1317
+ }
1318
+ }
1319
+
1320
+ const { SessionFileMonitor } = await import('./session-monitor');
1321
+ const filePath = SessionFileMonitor.resolveSessionPath(this.projectPath, config.workDir, sessionId);
1322
+ this.sessionMonitor.startMonitoring(agentId, filePath);
1323
+ }
1324
+
1325
+ // ─── Health Check — auto-heal agents ─────────────────
1326
+
1327
+ private startHealthCheck(): void {
1328
+ if (this.healthCheckTimer) return;
1329
+ this.healthCheckTimer = setInterval(() => this.runHealthCheck(), 10_000);
1330
+ this.healthCheckTimer.unref();
1331
+ }
1332
+
1333
+ private stopHealthCheck(): void {
1334
+ if (this.healthCheckTimer) {
1335
+ clearInterval(this.healthCheckTimer);
1336
+ this.healthCheckTimer = null;
1337
+ }
1338
+ }
1339
+
1340
+ private runHealthCheck(): void {
1341
+ if (!this.daemonActive) return;
1342
+
1343
+ // Every 60s (6 ticks × 10s): reconcile agentRunningMsg cache with actual bus log
1344
+ this.reconcileTick++;
1345
+ if (this.reconcileTick >= 6) {
1346
+ this.reconcileTick = 0;
1347
+ const log = this.bus.getLog();
1348
+ for (const [agentId, messageId] of this.agentRunningMsg) {
1349
+ const msg = log.find(m => m.id === messageId);
1350
+ if (!msg || msg.status !== 'running') {
1351
+ console.log(`[health] reconcile: clearing stale agentRunningMsg for ${agentId} (msg=${messageId.slice(0, 8)}, status=${msg?.status || 'not found'})`);
1352
+ this.agentRunningMsg.delete(agentId);
1353
+ }
1354
+ }
1355
+ }
1356
+
1357
+ for (const [id, entry] of this.agents) {
1358
+ if (entry.config.type === 'input') continue;
1359
+
1360
+ // Check 1: Worker should exist for all active agents
1361
+ if (!entry.worker) {
1362
+ console.log(`[health] ${entry.config.label}: no worker — recreating`);
1363
+ this.enterDaemonListening(id);
1364
+ entry.state.smithStatus = 'active';
1365
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'active' } as any);
1366
+ continue;
1367
+ }
1368
+
1369
+ // Check 2: SmithStatus should be active
1370
+ // Skip: 'starting' means ensurePersistentSession is in progress — overriding would race with it.
1371
+ if (entry.state.smithStatus !== 'active' && entry.state.smithStatus !== 'starting') {
1372
+ console.log(`[health] ${entry.config.label}: smith=${entry.state.smithStatus} — setting active`);
1373
+ entry.state.smithStatus = 'active';
1374
+ this.emit('event', { type: 'smith_status', agentId: id, smithStatus: 'active' } as any);
1375
+ }
1376
+
1377
+ // Check 3: Message loop should be running
1378
+ if (!this.messageLoopTimers.has(id)) {
1379
+ console.log(`[health] ${entry.config.label}: message loop stopped — restarting`);
1380
+ this.startMessageLoop(id);
1381
+ }
1382
+
1383
+ // Check 4: Stale running messages (agent not actually running) → mark failed
1384
+ if (entry.state.taskStatus !== 'running') {
1385
+ const staleRunning = this.bus.getLog().filter(m => m.to === id && m.status === 'running' && m.type !== 'ack');
1386
+ for (const m of staleRunning) {
1387
+ const age = Date.now() - m.timestamp;
1388
+ if (age > 60_000) { // running for 60s+ but agent is idle = stale
1389
+ console.log(`[health] ${entry.config.label}: stale running message ${m.id.slice(0, 8)} (${Math.round(age/1000)}s) — marking failed`);
1390
+ m.status = 'failed';
1391
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'failed' } as any);
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+ // Check 5: Pending messages but agent idle — try wake
1397
+ if (entry.state.taskStatus !== 'running') {
1398
+ const pending = this.bus.getPendingMessagesFor(id).filter(m => m.from !== id && m.type !== 'ack');
1399
+ if (pending.length > 0 && entry.worker?.isListening()) {
1400
+ // Message loop should handle this, but if it didn't, log it
1401
+ const age = Date.now() - pending[0].timestamp;
1402
+ if (age > 30_000) { // stuck for 30+ seconds
1403
+ console.log(`[health] ${entry.config.label}: ${pending.length} pending msg(s) stuck for ${Math.round(age/1000)}s — message loop should pick up`);
1404
+ }
1405
+ }
1406
+ }
1407
+
1408
+ // Check 6: persistentSession agent without tmux → auto-restart terminal
1409
+ // Skip if smithStatus='starting': ensurePersistentSession is already in progress.
1410
+ if (entry.config.persistentSession && !entry.state.tmuxSession && entry.state.smithStatus === 'active') {
1411
+ console.log(`[health] ${entry.config.label}: persistentSession but no tmux — restarting terminal`);
1412
+ this.ensurePersistentSession(id, entry.config).catch(err => {
1413
+ console.error(`[health] ${entry.config.label}: failed to restart terminal: ${err.message}`);
1414
+ });
1415
+ }
1416
+ }
1417
+
1418
+ // ── Forge Agent: autonomous bus monitor ──
1419
+ this.runForgeAgentCheck();
1420
+ }
1421
+
1422
+ // Track which messages Forge agent already acted on (avoid duplicate nudges)
1423
+ private forgeActedMessages = new Set<string>();
1424
+ private forgeAgentStartTime = 0;
1425
+
1426
+ /** Forge agent scans bus for actionable states (only recent messages) */
1427
+ private runForgeAgentCheck(): void {
1428
+ if (!this.forgeAgentStartTime) this.forgeAgentStartTime = Date.now();
1429
+ const log = this.bus.getLog();
1430
+ const now = Date.now();
1431
+
1432
+ // Pre-build reply index: "from→to" → latest non-ack message timestamp (only after daemon start)
1433
+ // Used for O(1) hasReply lookups instead of O(n) log.some() per message
1434
+ const replyIndex = new Map<string, number>();
1435
+ for (const r of log) {
1436
+ if (r.timestamp < this.forgeAgentStartTime) continue;
1437
+ if (r.type === 'ack') continue;
1438
+ const key = `${r.from}→${r.to}`;
1439
+ if ((replyIndex.get(key) || 0) < r.timestamp) replyIndex.set(key, r.timestamp);
1440
+ }
1441
+
1442
+ // Only scan messages from after daemon start (skip all history)
1443
+ for (const msg of log) {
1444
+ if (msg.timestamp < this.forgeAgentStartTime) continue;
1445
+ if (msg.type === 'ack' || msg.from === '_forge') continue;
1446
+ if (this.forgeActedMessages.has(msg.id)) continue;
1447
+
1448
+ // Case 1: Message done but no reply from target → ask target to send summary (once per pair)
1449
+ // Skip notification-only messages that don't need replies
1450
+ if (msg.status === 'done') {
1451
+ const action = msg.payload?.action;
1452
+ if (action === 'upstream_complete' || action === 'task_complete' || action === 'ack') { this.forgeActedMessages.add(msg.id); continue; }
1453
+ if (msg.from === '_system' || msg.from === '_watch') { this.forgeActedMessages.add(msg.id); continue; }
1454
+ const age = now - msg.timestamp;
1455
+ if (age < 30_000) continue;
1456
+
1457
+ // Dedup by target→sender pair (only nudge once per relationship)
1458
+ const nudgeKey = `nudge-${msg.to}->${msg.from}`;
1459
+ if (this.forgeActedMessages.has(nudgeKey)) { this.forgeActedMessages.add(msg.id); continue; }
1460
+
1461
+ const hasReply = (replyIndex.get(`${msg.to}→${msg.from}`) || 0) > msg.timestamp;
1462
+ if (!hasReply) {
1463
+ const senderLabel = this.agents.get(msg.from)?.config.label || msg.from;
1464
+ const targetEntry = this.agents.get(msg.to);
1465
+ if (targetEntry && targetEntry.state.smithStatus === 'active') {
1466
+ this.bus.send('_forge', msg.to, 'notify', {
1467
+ action: 'info_request',
1468
+ content: `[IMPORTANT] You finished a task requested by ${senderLabel} but did not send them the results. You MUST call the MCP tool "send_message" (NOT the forge-send skill) with to="${senderLabel}" and include a summary of what you did and the outcome. Do not do any other work until you have sent this reply.`,
1469
+ });
1470
+ this.forgeActedMessages.add(msg.id);
1471
+ this.forgeActedMessages.add(nudgeKey);
1472
+ console.log(`[forge-agent] Nudged ${targetEntry.config.label} to reply to ${senderLabel} (once)`);
1473
+ }
1474
+ }
1475
+ }
1476
+
1477
+ // Case 2: Message running too long (>5min) → log warning
1478
+ if (msg.status === 'running') {
1479
+ const age = now - msg.timestamp;
1480
+ if (age > 300_000 && !this.forgeActedMessages.has(`running-${msg.id}`)) {
1481
+ const targetLabel = this.agents.get(msg.to)?.config.label || msg.to;
1482
+ console.log(`[forge-agent] Warning: ${targetLabel} has been running message ${msg.id.slice(0, 8)} for ${Math.round(age / 60000)}min`);
1483
+ this.emit('event', { type: 'log', agentId: msg.to, entry: { type: 'system', subtype: 'warning', content: `Message running for ${Math.round(age / 60000)}min — may be stuck`, timestamp: new Date().toISOString() } } as any);
1484
+ this.forgeActedMessages.add(`running-${msg.id}`);
1485
+ }
1486
+ }
1487
+
1488
+ // Case 3: Pending too long (>2min) → try to restart message loop
1489
+ if (msg.status === 'pending') {
1490
+ const age = now - msg.timestamp;
1491
+ if (age > 120_000 && !this.forgeActedMessages.has(`pending-${msg.id}`)) {
1492
+ const targetEntry = this.agents.get(msg.to);
1493
+ const targetLabel = targetEntry?.config.label || msg.to;
1494
+
1495
+ // If agent is active but not running a task, restart message loop
1496
+ if (targetEntry && targetEntry.state.smithStatus === 'active' && targetEntry.state.taskStatus !== 'running') {
1497
+ if (!this.messageLoopTimers.has(msg.to)) {
1498
+ this.startMessageLoop(msg.to);
1499
+ console.log(`[forge-agent] Restarted message loop for ${targetLabel} (pending ${Math.round(age / 60000)}min)`);
1500
+ } else {
1501
+ console.log(`[forge-agent] ${targetLabel} has pending message ${msg.id.slice(0, 8)} for ${Math.round(age / 60000)}min — loop running but not consuming`);
1502
+ }
1503
+ }
1504
+
1505
+ this.emit('event', { type: 'log', agentId: msg.to, entry: { type: 'system', subtype: 'warning', content: `Pending message from ${this.agents.get(msg.from)?.config.label || msg.from} waiting for ${Math.round(age / 60000)}min`, timestamp: new Date().toISOString() } } as any);
1506
+ this.forgeActedMessages.add(`pending-${msg.id}`);
1507
+ }
1508
+ }
1509
+
1510
+ // Case 4: Failed → notify sender (once per sender→target pair)
1511
+ if (msg.status === 'failed') {
1512
+ const failKey = `failed-${msg.from}->${msg.to}`;
1513
+ if (!this.forgeActedMessages.has(failKey)) {
1514
+ const senderEntry = this.agents.get(msg.from);
1515
+ const targetLabel = this.agents.get(msg.to)?.config.label || msg.to;
1516
+ if (senderEntry && msg.from !== '_forge' && msg.from !== '_system') {
1517
+ this.bus.send('_forge', msg.from, 'notify', {
1518
+ action: 'update_notify',
1519
+ content: `Your message to ${targetLabel} has failed. You may want to retry or take a different approach.`,
1520
+ });
1521
+ console.log(`[forge-agent] Notified ${senderEntry.config.label} that message to ${targetLabel} failed (once)`);
1522
+ }
1523
+ this.forgeActedMessages.add(failKey);
1524
+ }
1525
+ this.forgeActedMessages.add(`failed-${msg.id}`);
1526
+ }
1527
+
1528
+ // Case 5: Pending approval too long (>5min) → log reminder
1529
+ if (msg.status === 'pending_approval') {
1530
+ const age = now - msg.timestamp;
1531
+ if (age > 300_000 && !this.forgeActedMessages.has(`approval-${msg.id}`)) {
1532
+ const targetLabel = this.agents.get(msg.to)?.config.label || msg.to;
1533
+ this.emit('event', { type: 'log', agentId: msg.to, entry: { type: 'system', subtype: 'warning', content: `Message awaiting approval for ${Math.round(age / 60000)}min — requires manual action`, timestamp: new Date().toISOString() } } as any);
1534
+ this.forgeActedMessages.add(`approval-${msg.id}`);
1535
+ }
1536
+ }
1537
+ }
1538
+ }
1539
+
1540
+ /** Handle watch alert based on agent's configured action */
1541
+ private handleWatchAlert(agentId: string, summary: string): void {
1542
+ const entry = this.agents.get(agentId);
1543
+ if (!entry) return;
1544
+ const action = entry.config.watch?.action || 'log';
1545
+
1546
+ if (action === 'log') {
1547
+ // Already logged by watch-manager, nothing more to do
1548
+ return;
1549
+ }
1550
+
1551
+ if (action === 'analyze') {
1552
+ // Auto-wake agent to analyze changes (skip if busy/manual)
1553
+ if (entry.state.taskStatus === 'running') {
1554
+ console.log(`[watch] ${entry.config.label}: skipped analyze (task=${entry.state.taskStatus})`);
1555
+ return;
1556
+ }
1557
+ if (!entry.worker?.isListening()) {
1558
+ console.log(`[watch] ${entry.config.label}: skipped analyze (worker=${!!entry.worker} listening=${entry.worker?.isListening()})`);
1559
+ return;
1560
+ }
1561
+ console.log(`[watch] ${entry.config.label}: triggering analyze`);
1562
+
1563
+ const prompt = entry.config.watch?.prompt || 'Analyze the following changes and produce a report:';
1564
+ const logEntry = {
1565
+ type: 'system' as const,
1566
+ subtype: 'watch_trigger',
1567
+ content: `[Watch] ${prompt}\n\n${summary}`,
1568
+ timestamp: new Date().toISOString(),
1569
+ };
1570
+ entry.worker.wake({ type: 'bus_message', messages: [logEntry] });
1571
+ console.log(`[watch] ${entry.config.label}: auto-analyzing detected changes`);
1572
+ return;
1573
+ }
1574
+
1575
+ if (action === 'approve') {
1576
+ // Create message with pending_approval status — user must approve to execute
1577
+ const msg = this.bus.send('_watch', agentId, 'notify', {
1578
+ action: 'watch_changes',
1579
+ content: `Watch detected changes (awaiting approval):\n${summary}`,
1580
+ });
1581
+ msg.status = 'pending_approval';
1582
+ this.emit('event', { type: 'bus_message_status', messageId: msg.id, status: 'pending_approval' } as any);
1583
+ console.log(`[watch] ${entry.config.label}: changes detected, awaiting approval`);
1584
+ }
1585
+
1586
+ if (action === 'send_message') {
1587
+ const targetId = entry.config.watch?.sendTo;
1588
+ if (!targetId) {
1589
+ console.log(`[watch] ${entry.config.label}: send_message but no sendTo configured`);
1590
+ return;
1591
+ }
1592
+ const targetEntry = this.agents.get(targetId);
1593
+ if (!targetEntry) {
1594
+ console.log(`[watch] ${entry.config.label}: sendTo agent ${targetId} not found`);
1595
+ return;
1596
+ }
1597
+
1598
+ const prompt = entry.config.watch?.prompt;
1599
+ // For terminal injection: send the configured prompt directly (pattern is the trigger, not the payload)
1600
+ // If no prompt configured, send the summary
1601
+ const message = prompt || summary;
1602
+
1603
+ // Try to inject directly into an open terminal session
1604
+ // Verify stored session is alive, clear if dead
1605
+ if (targetEntry.state.tmuxSession) {
1606
+ try { execSync(`tmux has-session -t "${targetEntry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 }); }
1607
+ catch { targetEntry.state.tmuxSession = undefined; }
1608
+ }
1609
+ const tmuxSession = targetEntry.state.tmuxSession || this.findTmuxSession(targetEntry.config.label);
1610
+ if (tmuxSession) {
1611
+ try {
1612
+ const tmpFile = `/tmp/forge-watch-${Date.now()}.txt`;
1613
+ writeFileSync(tmpFile, message);
1614
+ execSync(`tmux load-buffer ${tmpFile}`, { timeout: 5000 });
1615
+ execSync(`tmux paste-buffer -t "${tmuxSession}" && sleep 0.2 && tmux send-keys -t "${tmuxSession}" Enter`, { timeout: 5000 });
1616
+ try { unlinkSync(tmpFile); } catch {}
1617
+ console.log(`[watch] ${entry.config.label} → ${targetEntry.config.label}: injected into terminal (${tmuxSession})`);
1618
+ } catch (err: any) {
1619
+ console.error(`[watch] Terminal inject failed: ${err.message}, falling back to bus`);
1620
+ this.bus.send(agentId, targetId, 'notify', { action: 'watch_alert', content: message });
1621
+ }
1622
+ return;
1623
+ }
1624
+
1625
+ // No terminal open — send via bus (will start new session)
1626
+ const hasPendingFromWatch = this.bus.getLog().some(m =>
1627
+ m.from === agentId && m.to === targetId &&
1628
+ (m.status === 'pending' || m.status === 'running' || m.status === 'pending_approval') &&
1629
+ m.type !== 'ack'
1630
+ );
1631
+ if (hasPendingFromWatch) {
1632
+ console.log(`[watch] ${entry.config.label}: skipping bus send — target still processing`);
1633
+ return;
1634
+ }
1635
+
1636
+ this.bus.send(agentId, targetId, 'notify', { action: 'watch_alert', content: message });
1637
+ console.log(`[watch] ${entry.config.label} → ${targetEntry.config.label}: sent via bus`);
1638
+ }
1639
+ }
1640
+
1641
+ /** Check if daemon mode is active */
1642
+ isDaemonActive(): boolean {
1643
+ return this.daemonActive;
1644
+ }
1645
+
1646
+ /** Pause a running agent */
1647
+ pauseAgent(agentId: string): void {
1648
+ const entry = this.agents.get(agentId);
1649
+ entry?.worker?.pause();
1650
+ }
1651
+
1652
+ /** Resume a paused agent */
1653
+ resumeAgent(agentId: string): void {
1654
+ const entry = this.agents.get(agentId);
1655
+ entry?.worker?.resume();
1656
+ }
1657
+
1658
+ /** Stop a running agent */
1659
+ /** Mark agent task as done (user manually confirms completion) */
1660
+ markAgentDone(agentId: string, notify: boolean): void {
1661
+ const entry = this.agents.get(agentId);
1662
+ if (!entry) return;
1663
+
1664
+ // Mark running inbox messages as done
1665
+ const runningMsgs = this.bus.getLog().filter(m => m.to === agentId && m.status === 'running' && m.type !== 'ack');
1666
+ for (const m of runningMsgs) {
1667
+ m.status = 'done' as any;
1668
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'done' } as any);
1669
+ }
1670
+
1671
+ entry.state.taskStatus = notify ? 'done' : 'idle';
1672
+ entry.state.completedAt = Date.now();
1673
+ this.emit('event', { type: 'task_status', agentId, taskStatus: entry.state.taskStatus } as any);
1674
+ if (notify) {
1675
+ this.handleAgentDone(agentId, entry, 'Manually marked done');
1676
+ }
1677
+ this.sessionMonitor?.resetState(agentId);
1678
+ this.saveNow();
1679
+ this.emitAgentsChanged();
1680
+ console.log(`[workspace] ${entry.config.label}: manually marked ${notify ? 'done' : 'idle'} (${runningMsgs.length} messages completed)`);
1681
+ }
1682
+
1683
+ /** Mark agent task as failed (user manually marks failure) */
1684
+ markAgentFailed(agentId: string, notify: boolean): void {
1685
+ const entry = this.agents.get(agentId);
1686
+ if (!entry) return;
1687
+
1688
+ // Mark running inbox messages as failed
1689
+ const runningMsgs = this.bus.getLog().filter(m => m.to === agentId && m.status === 'running' && m.type !== 'ack');
1690
+ for (const m of runningMsgs) {
1691
+ m.status = 'failed' as any;
1692
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'failed' } as any);
1693
+ }
1694
+
1695
+ entry.state.taskStatus = 'failed';
1696
+ entry.state.error = 'Manually marked as failed';
1697
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'failed' } as any);
1698
+ if (notify) {
1699
+ this.bus.notifyTaskComplete(agentId, [], 'Task failed');
1700
+ }
1701
+ this.sessionMonitor?.resetState(agentId);
1702
+ this.saveNow();
1703
+ this.emitAgentsChanged();
1704
+ console.log(`[workspace] ${entry.config.label}: manually marked failed (${runningMsgs.length} messages failed)`);
1705
+ }
1706
+
1707
+ /** Legacy stop — for headless mode */
1708
+ stopAgent(agentId: string): void {
1709
+ const entry = this.agents.get(agentId);
1710
+ if (!entry) return;
1711
+ if (entry.config.persistentSession) {
1712
+ this.markAgentDone(agentId, false);
1713
+ } else {
1714
+ entry.worker?.stop();
1715
+ }
1716
+ }
1717
+
1718
+ /** Retry a failed agent from its last checkpoint */
1719
+ async retryAgent(agentId: string): Promise<void> {
1720
+ const entry = this.agents.get(agentId);
1721
+ if (!entry) throw new Error(`Agent "${agentId}" not found`);
1722
+ if (entry.state.taskStatus === 'running') {
1723
+ throw new Error(`Agent "${entry.config.label}" is already running`);
1724
+ }
1725
+ if (entry.state.taskStatus !== 'failed') {
1726
+ throw new Error(`Agent "${entry.config.label}" is ${entry.state.taskStatus}, not failed`);
1727
+ }
1728
+ // force=true: skip dep taskStatus check, only require upstream smith active
1729
+ await this.runAgent(agentId, undefined, true);
1730
+ }
1731
+
1732
+ /** Send a message to a running agent (human intervention) */
1733
+ /** Send a message to a smith — becomes a pending inbox message, processed by message loop */
1734
+ sendMessageToAgent(agentId: string, content: string): void {
1735
+ const entry = this.agents.get(agentId);
1736
+ if (!entry) return;
1737
+
1738
+ // Send via bus → becomes pending inbox message → message loop will consume it
1739
+ this.bus.send('user', agentId, 'notify', {
1740
+ action: 'user_message',
1741
+ content,
1742
+ });
1743
+ }
1744
+
1745
+ /** Approve a waiting agent to start execution */
1746
+ approveAgent(agentId: string): void {
1747
+ if (!this.approvalQueue.has(agentId)) return;
1748
+ this.approvalQueue.delete(agentId);
1749
+ this.runAgent(agentId).catch(() => {});
1750
+ }
1751
+
1752
+ /** Save tmux session name for an agent (for reattach after refresh) */
1753
+ setTmuxSession(agentId: string, sessionName: string): void {
1754
+ const entry = this.agents.get(agentId);
1755
+ if (!entry) return;
1756
+ entry.state.tmuxSession = sessionName;
1757
+ this.saveNow();
1758
+ this.emitAgentsChanged();
1759
+ }
1760
+
1761
+ clearTmuxSession(agentId: string): void {
1762
+ const entry = this.agents.get(agentId);
1763
+ if (!entry) return;
1764
+ entry.state.tmuxSession = undefined;
1765
+ // Reset session monitor warmup so it doesn't immediately trigger running on restart
1766
+ this.sessionMonitor?.resetState(agentId);
1767
+ this.saveNow();
1768
+ this.emitAgentsChanged();
1769
+ }
1770
+
1771
+ /** Record that an agent has an open terminal (tmux session tracking) */
1772
+ setManualMode(agentId: string): void {
1773
+ const entry = this.agents.get(agentId);
1774
+ if (!entry) return;
1775
+ // tmuxSession is set separately when terminal opens
1776
+ this.emitAgentsChanged();
1777
+ this.saveNow();
1778
+ console.log(`[workspace] Agent "${entry.config.label}" terminal opened`);
1779
+ }
1780
+
1781
+ /** Called when agent's terminal is closed */
1782
+ restartAgentDaemon(agentId: string): void {
1783
+ if (!this.daemonActive) return;
1784
+ const entry = this.agents.get(agentId);
1785
+ if (!entry || entry.config.type === 'input') return;
1786
+
1787
+ entry.state.error = undefined;
1788
+ // Don't clear tmuxSession here — it may still be alive (persistent session)
1789
+ // Terminal close just means the UI panel is closed, not necessarily tmux killed
1790
+
1791
+ // Recreate worker if needed
1792
+ if (!entry.worker) {
1793
+ this.enterDaemonListening(agentId);
1794
+ this.startMessageLoop(agentId);
1795
+ }
1796
+
1797
+ entry.state.smithStatus = 'active';
1798
+ this.emit('event', { type: 'smith_status', agentId, smithStatus: 'active' } satisfies WorkerEvent);
1799
+ this.emitAgentsChanged();
1800
+ }
1801
+
1802
+ /** Complete an agent from terminal — called by forge-done skill */
1803
+ completeManualAgent(agentId: string, changedFiles: string[]): void {
1804
+ const entry = this.agents.get(agentId);
1805
+ if (!entry) return;
1806
+
1807
+ entry.state.taskStatus = 'done';
1808
+ entry.state.completedAt = Date.now();
1809
+ entry.state.artifacts = changedFiles.map(f => ({ type: 'file' as const, path: f }));
1810
+
1811
+ console.log(`[workspace] Manual agent "${entry.config.label}" marked done. ${changedFiles.length} files changed.`);
1812
+
1813
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'done' } satisfies WorkerEvent);
1814
+ this.emit('event', { type: 'done', agentId, summary: `Manual: ${changedFiles.length} files changed` } satisfies WorkerEvent);
1815
+ this.emitAgentsChanged();
1816
+
1817
+ // Notify ALL agents that depend on this one (not just direct downstream)
1818
+ this.bus.notifyTaskComplete(agentId, changedFiles, `Manual work: ${changedFiles.length} files`);
1819
+
1820
+ // Send individual bus messages to all downstream agents so they know
1821
+ for (const [id, other] of this.agents) {
1822
+ if (id === agentId || other.config.type === 'input') continue;
1823
+ if (other.config.dependsOn.includes(agentId)) {
1824
+ this.bus.send(agentId, id, 'notify', {
1825
+ action: 'update_notify',
1826
+ content: `${entry.config.label} completed manual work: ${changedFiles.length} files changed`,
1827
+ files: changedFiles,
1828
+ });
1829
+ }
1830
+ }
1831
+
1832
+ if (this.daemonActive) {
1833
+ this.broadcastCompletion(agentId);
1834
+ }
1835
+ this.notifyDownstreamForRevalidation(agentId, changedFiles);
1836
+ this.emitWorkspaceStatus();
1837
+ this.checkWorkspaceComplete();
1838
+ this.saveNow();
1839
+ }
1840
+
1841
+ /** Reject an approval (set agent back to idle) */
1842
+ rejectApproval(agentId: string): void {
1843
+ this.approvalQueue.delete(agentId);
1844
+ const entry = this.agents.get(agentId);
1845
+ if (entry) {
1846
+ entry.state.taskStatus = 'idle';
1847
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'idle' } satisfies WorkerEvent);
1848
+ }
1849
+ }
1850
+
1851
+ // ─── Bus Access ────────────────────────────────────────
1852
+
1853
+ getBus(): AgentBus {
1854
+ return this.bus;
1855
+ }
1856
+
1857
+ getBusLog(): readonly BusMessage[] {
1858
+ return this.bus.getLog();
1859
+ }
1860
+
1861
+ // ─── State Snapshot (for persistence) ──────────────────
1862
+
1863
+ /** Get full workspace state for auto-save */
1864
+ getFullState(): WorkspaceState {
1865
+ return {
1866
+ id: this.workspaceId,
1867
+ projectPath: this.projectPath,
1868
+ projectName: this.projectName,
1869
+ agents: Array.from(this.agents.values()).map(e => e.config),
1870
+ agentStates: this.getAllAgentStates(),
1871
+ nodePositions: {},
1872
+ busLog: [...this.bus.getLog()],
1873
+ busOutbox: this.bus.getAllOutbox(),
1874
+ createdAt: this.createdAt,
1875
+ updatedAt: Date.now(),
1876
+ };
1877
+ }
1878
+
1879
+ getSnapshot(): {
1880
+ agents: WorkspaceAgentConfig[];
1881
+ agentStates: Record<string, AgentState>;
1882
+ busLog: BusMessage[];
1883
+ daemonActive: boolean;
1884
+ } {
1885
+ return {
1886
+ agents: Array.from(this.agents.values()).map(e => e.config),
1887
+ agentStates: this.getAllAgentStates(),
1888
+ busLog: [...this.bus.getLog()],
1889
+ daemonActive: this.daemonActive,
1890
+ };
1891
+ }
1892
+
1893
+ /** Restore from persisted state */
1894
+ loadSnapshot(data: {
1895
+ agents: WorkspaceAgentConfig[];
1896
+ agentStates: Record<string, AgentState>;
1897
+ busLog: BusMessage[];
1898
+ busOutbox?: Record<string, BusMessage[]>;
1899
+ }): void {
1900
+ this.agents.clear();
1901
+ this.daemonActive = false; // Reset daemon — user must click Start Daemon again after restart
1902
+ for (const config of data.agents) {
1903
+ const state = data.agentStates[config.id] || { smithStatus: 'down' as const, taskStatus: 'idle' as const, history: [], artifacts: [] };
1904
+
1905
+ // Migrate old format if loading from pre-two-layer state
1906
+ if ('status' in state && !('smithStatus' in state)) {
1907
+ const oldStatus = (state as any).status;
1908
+ (state as any).smithStatus = 'down';
1909
+ (state as any).taskStatus = (oldStatus === 'running' || oldStatus === 'listening') ? 'idle' :
1910
+ (oldStatus === 'interrupted') ? 'idle' :
1911
+ (oldStatus === 'waiting_approval') ? 'idle' :
1912
+ (oldStatus === 'paused') ? 'idle' :
1913
+ oldStatus;
1914
+ delete (state as any).status;
1915
+ delete (state as any).runMode;
1916
+ delete (state as any).daemonMode;
1917
+ }
1918
+
1919
+ // Mark running agents as failed (interrupted by restart)
1920
+ if (state.taskStatus === 'running') {
1921
+ state.taskStatus = 'failed';
1922
+ state.error = 'Interrupted by restart';
1923
+ }
1924
+ // Smith is down after restart (no daemon loop running)
1925
+ state.smithStatus = 'down';
1926
+ state.daemonIteration = undefined;
1927
+ this.agents.set(config.id, { config, worker: null, state });
1928
+ }
1929
+ this.bus.loadLog(data.busLog);
1930
+ if (data.busOutbox) {
1931
+ this.bus.loadOutbox(data.busOutbox);
1932
+ }
1933
+
1934
+ // Mark all pending messages as failed (they were lost on shutdown)
1935
+ // Users can retry agents manually if needed
1936
+ // Running messages from before crash → failed (pending stays pending for retry)
1937
+ this.bus.markAllRunningAsFailed();
1938
+
1939
+ // Initialize liveness for all loaded agents so bus delivery works
1940
+ for (const [agentId] of this.agents) {
1941
+ this.updateAgentLiveness(agentId);
1942
+ }
1943
+ }
1944
+
1945
+ /** Stop all agents, save final state, and clean up */
1946
+ shutdown(): void {
1947
+ this.daemonActive = false;
1948
+ this.stopHealthCheck();
1949
+ this.stopAllMessageLoops();
1950
+ stopAutoSave(this.workspaceId);
1951
+ // Sync save — must complete before process exits
1952
+ try { saveWorkspaceSync(this.getFullState()); } catch (err) {
1953
+ console.error(`[workspace] Failed to save on shutdown:`, err);
1954
+ }
1955
+ for (const [, entry] of this.agents) {
1956
+ entry.worker?.stop();
1957
+ }
1958
+ this.bus.clear();
1959
+ }
1960
+
1961
+ // ─── Private ───────────────────────────────────────────
1962
+
1963
+ /** Rebuild workspace topology cache — called on agent changes and daemon start */
1964
+ private rebuildTopo(): void {
1965
+ // Topological sort
1966
+ const sorted: WorkspaceAgentConfig[] = [];
1967
+ const visited = new Set<string>();
1968
+ const entries = Array.from(this.agents.values()).filter(e => e.config.type !== 'input');
1969
+ const configMap = new Map(entries.map(e => [e.config.id, e.config]));
1970
+
1971
+ const visit = (id: string) => {
1972
+ if (visited.has(id)) return;
1973
+ visited.add(id);
1974
+ const c = configMap.get(id);
1975
+ if (!c) return;
1976
+ for (const dep of c.dependsOn) visit(dep);
1977
+ sorted.push(c);
1978
+ };
1979
+ for (const e of entries) visit(e.config.id);
1980
+
1981
+ const agents: TopoAgent[] = sorted.map(c => {
1982
+ const state = this.agents.get(c.id)?.state;
1983
+ return {
1984
+ id: c.id,
1985
+ label: c.label,
1986
+ icon: c.icon,
1987
+ role: c.role || '',
1988
+ roleSummary: (c.role || '').split('\n')[0].slice(0, 150),
1989
+ primary: !!c.primary,
1990
+ dependsOn: c.dependsOn.map(d => this.agents.get(d)?.config.label || d),
1991
+ dependsOnIds: [...c.dependsOn],
1992
+ workDir: c.workDir || './',
1993
+ outputs: c.outputs || [],
1994
+ steps: (c.steps || []).map(s => s.label),
1995
+ smithStatus: state?.smithStatus || 'down',
1996
+ taskStatus: state?.taskStatus || 'idle',
1997
+ };
1998
+ });
1999
+
2000
+ this._topoCache = {
2001
+ agents,
2002
+ flow: sorted.map(c => c.label).join(' → '),
2003
+ updatedAt: Date.now(),
2004
+ };
2005
+ }
2006
+
2007
+ /** Get cached workspace topology (always fresh — rebuilt on every agent change) */
2008
+ getWorkspaceTopo(): WorkspaceTopo {
2009
+ if (!this._topoCache) this.rebuildTopo();
2010
+ return this._topoCache!;
2011
+ }
2012
+
2013
+ /** Remove stale Forge blocks from all agents' CLAUDE.md files (migration cleanup).
2014
+ * Role is no longer written to CLAUDE.md — this just removes legacy artifacts. */
2015
+ private cleanLegacyClaudeMdBlocks(): void {
2016
+ const roleRegex = /<!-- forge:agent-role -->[\s\S]*?<!-- \/forge:agent-role -->\n?/;
2017
+ const topoRegex = /<!-- forge:workspace-topo -->[\s\S]*?<!-- \/forge:workspace-topo -->\n?/;
2018
+
2019
+ for (const [, entry] of this.agents) {
2020
+ if (entry.config.type === 'input') continue;
2021
+ const workDir = join(this.projectPath, entry.config.workDir || '');
2022
+ const claudeMdPath = join(workDir, 'CLAUDE.md');
2023
+ if (!existsSync(claudeMdPath)) continue;
2024
+
2025
+ try {
2026
+ let content = readFileSync(claudeMdPath, 'utf-8');
2027
+ const before = content;
2028
+ if (roleRegex.test(content)) content = content.replace(roleRegex, '');
2029
+ if (topoRegex.test(content)) content = content.replace(topoRegex, '');
2030
+ if (content !== before) {
2031
+ content = content.trimEnd() + (content.trim() ? '\n' : '');
2032
+ if (content.trim()) writeFileSync(claudeMdPath, content);
2033
+ else unlinkSync(claudeMdPath); // was only forge content, delete empty file
2034
+ console.log(`[workspace] Cleaned legacy Forge blocks from ${claudeMdPath}`);
2035
+ }
2036
+ } catch (err: any) {
2037
+ console.warn(`[workspace] Failed to clean CLAUDE.md at ${claudeMdPath}: ${err.message}`);
2038
+ }
2039
+ }
2040
+ }
2041
+
2042
+ private createBackend(config: WorkspaceAgentConfig, agentId?: string) {
2043
+ switch (config.backend) {
2044
+ case 'api':
2045
+ // TODO: ApiBackend uses @/src path aliases that don't work in standalone tsx.
2046
+ // Need to refactor api-backend imports before enabling.
2047
+ throw new Error('API backend not yet supported in workspace daemon. Use CLI backend instead.');
2048
+ case 'cli':
2049
+ default: {
2050
+ // Resume existing claude session if available
2051
+ const existingSessionId = agentId ? this.agents.get(agentId)?.state.cliSessionId : undefined;
2052
+ const backend = new CliBackend(existingSessionId);
2053
+ // Persist new sessionId back to agent state
2054
+ if (agentId) {
2055
+ backend.onSessionId = (id) => {
2056
+ const entry = this.agents.get(agentId);
2057
+ if (entry) entry.state.cliSessionId = id;
2058
+ };
2059
+ }
2060
+ return backend;
2061
+ }
2062
+ }
2063
+ }
2064
+
2065
+ /** Build a compact topo summary injected into every agent task */
2066
+ private buildTopoSummary(selfId: string): string {
2067
+ const topo = this.getWorkspaceTopo();
2068
+ if (topo.agents.length === 0) return '';
2069
+
2070
+ const lines: string[] = ['## Workspace Team'];
2071
+ lines.push(`Flow: ${topo.flow}`);
2072
+
2073
+ // Missing roles hint
2074
+ const labels = new Set(topo.agents.map(a => a.label.toLowerCase()));
2075
+ const standard = ['architect', 'engineer', 'qa', 'reviewer', 'pm', 'lead'];
2076
+ const missing = standard.filter(r => !labels.has(r));
2077
+ if (missing.length > 0) lines.push(`Missing: ${missing.join(', ')}`);
2078
+
2079
+ for (const a of topo.agents) {
2080
+ const me = a.id === selfId ? ' ← you' : '';
2081
+ const status = `${a.smithStatus}/${a.taskStatus}`;
2082
+ lines.push(`- ${a.icon} ${a.label}${me} [${status}]: ${a.roleSummary}`);
2083
+ }
2084
+ return lines.join('\n');
2085
+ }
2086
+
2087
+ /** Build full role preamble — injected once when persistent session starts */
2088
+ private buildRolePreamble(config: WorkspaceAgentConfig): string {
2089
+ const roleText = (config.role || '').trim() || '(no role defined)';
2090
+ return `=== SMITH CONTEXT (managed by Forge) ===
2091
+ You are ${config.label}. Work dir: ${config.workDir || './'}.
2092
+
2093
+ Your role and responsibilities:
2094
+ ${roleText}
2095
+
2096
+ ---
2097
+ Silently ingest this context. Do NOT respond — await an actual task.`;
2098
+ }
2099
+
2100
+ /** Build short role reminder — injected periodically to combat auto-compaction */
2101
+ private buildRoleReminder(config: WorkspaceAgentConfig): string {
2102
+ const roleText = (config.role || '').trim();
2103
+ // First 300 chars of role, plus label
2104
+ const summary = roleText.length > 300 ? roleText.slice(0, 300) + '...' : roleText;
2105
+ return `[Role reminder — you are ${config.label}]\n${summary}\n---`;
2106
+ }
2107
+
2108
+ /** Check if a role reminder should be re-injected before next bus message */
2109
+ private needsRoleReminder(agentId: string): boolean {
2110
+ const st = this.roleInjectState.get(agentId);
2111
+ if (!st) return false; // no preamble sent yet — session is starting
2112
+ const now = Date.now();
2113
+ const REMIND_EVERY_MSGS = 10;
2114
+ const REMIND_EVERY_MS = 30 * 60 * 1000; // 30 min
2115
+ if (st.msgsSinceInject >= REMIND_EVERY_MSGS) return true;
2116
+ if (now - st.lastInjectAt >= REMIND_EVERY_MS) return true;
2117
+ return false;
2118
+ }
2119
+
2120
+ /** Mark that role was just injected for this agent */
2121
+ private markRoleInjected(agentId: string): void {
2122
+ this.roleInjectState.set(agentId, { lastInjectAt: Date.now(), msgsSinceInject: 0 });
2123
+ }
2124
+
2125
+ /** Increment message counter since last role injection */
2126
+ private incrementMsgCount(agentId: string): void {
2127
+ const st = this.roleInjectState.get(agentId);
2128
+ if (st) st.msgsSinceInject++;
2129
+ }
2130
+
2131
+ /** Build context string from upstream agents' outputs */
2132
+ private buildUpstreamContext(config: WorkspaceAgentConfig): string | undefined {
2133
+ // Always prepend: role + workspace team summary
2134
+ const roleBlock = config.role?.trim() ? `## Your Role (${config.label})\n${config.role.trim()}` : '';
2135
+ const topoSummary = this.buildTopoSummary(config.id);
2136
+
2137
+ const headerSections: string[] = [];
2138
+ if (roleBlock) headerSections.push(roleBlock);
2139
+ if (topoSummary) headerSections.push(topoSummary);
2140
+ const header = headerSections.join('\n\n');
2141
+
2142
+ if (config.dependsOn.length === 0) {
2143
+ return header || undefined;
2144
+ }
2145
+
2146
+ const sections: string[] = [];
2147
+ if (header) sections.push(header);
2148
+
2149
+ for (const depId of config.dependsOn) {
2150
+ const dep = this.agents.get(depId);
2151
+ if (!dep || (dep.state.taskStatus !== 'done')) continue;
2152
+
2153
+ const label = dep.config.label;
2154
+
2155
+ // Input nodes: only send latest entry (not full history)
2156
+ if (dep.config.type === 'input') {
2157
+ const entries = dep.config.entries;
2158
+ if (entries && entries.length > 0) {
2159
+ const latest = entries[entries.length - 1];
2160
+ sections.push(`### ${label} (latest input):\n${latest.content}`);
2161
+ } else if (dep.config.content) {
2162
+ // Legacy fallback
2163
+ sections.push(`### ${label}:\n${dep.config.content}`);
2164
+ }
2165
+ continue;
2166
+ }
2167
+
2168
+ const artifacts = dep.state.artifacts.filter(a => a.path);
2169
+
2170
+ if (artifacts.length === 0) {
2171
+ const lastResult = [...dep.state.history].reverse().find(h => h.type === 'result');
2172
+ if (lastResult) {
2173
+ sections.push(`### From ${label}:\n${lastResult.content}`);
2174
+ }
2175
+ continue;
2176
+ }
2177
+
2178
+ // Read file artifacts
2179
+ for (const artifact of artifacts) {
2180
+ if (!artifact.path) continue;
2181
+ const fullPath = resolve(this.projectPath, artifact.path);
2182
+ try {
2183
+ if (existsSync(fullPath)) {
2184
+ const content = readFileSync(fullPath, 'utf-8');
2185
+ const truncated = content.length > 10000
2186
+ ? content.slice(0, 10000) + '\n... (truncated)'
2187
+ : content;
2188
+ sections.push(`### From ${label} — ${artifact.path}:\n${truncated}`);
2189
+ }
2190
+ } catch {
2191
+ sections.push(`### From ${label} — ${artifact.path}: (could not read file)`);
2192
+ }
2193
+ }
2194
+ }
2195
+
2196
+ if (sections.length === 0) return undefined;
2197
+
2198
+ let combined = sections.join('\n\n---\n\n');
2199
+
2200
+ // Cap total upstream context to ~50K chars (~12K tokens) to prevent token explosion
2201
+ const MAX_UPSTREAM_CHARS = 50000;
2202
+ if (combined.length > MAX_UPSTREAM_CHARS) {
2203
+ combined = combined.slice(0, MAX_UPSTREAM_CHARS) + '\n\n... (upstream context truncated, ' + combined.length + ' chars total)';
2204
+ }
2205
+
2206
+ return combined;
2207
+ }
2208
+
2209
+ /** After an agent completes, check if any downstream agents should be triggered */
2210
+ /**
2211
+ * Broadcast completion to all downstream agents via bus messages.
2212
+ * Replaces direct triggerDownstream — all execution is now message-driven.
2213
+ * If no artifacts/changes, no message is sent → downstream stays idle.
2214
+ */
2215
+ /** Build causedBy from the message currently being processed */
2216
+ private buildCausedBy(agentId: string, entry: { worker: AgentWorker | null }): BusMessage['causedBy'] | undefined {
2217
+ const msgId = entry.worker?.getCurrentMessageId?.();
2218
+ if (!msgId) return undefined;
2219
+ const msg = this.bus.getLog().find(m => m.id === msgId);
2220
+ if (!msg) return undefined;
2221
+ return { messageId: msg.id, from: msg.from, to: msg.to };
2222
+ }
2223
+
2224
+ /** Unified done handler: broadcast downstream or reply to sender based on message source */
2225
+ private handleAgentDone(agentId: string, entry: { config: WorkspaceAgentConfig; worker: AgentWorker | null; state: AgentState }, summary?: string): void {
2226
+ this.agentRunningMsg.delete(agentId);
2227
+ const files = entry.state.artifacts.filter(a => a.path).map(a => a.path!);
2228
+ console.log(`[workspace] Agent "${entry.config.label}" (${agentId}) completed. Artifacts: ${files.length}.`);
2229
+
2230
+ this.bus.notifyTaskComplete(agentId, files, summary);
2231
+
2232
+ // Check what message triggered this execution
2233
+ const causedBy = this.buildCausedBy(agentId, entry);
2234
+ const processedMsg = causedBy ? this.bus.getLog().find(m => m.id === causedBy.messageId) : null;
2235
+
2236
+ this.broadcastCompletion(agentId, causedBy);
2237
+ // Note: Forge agent (runForgeAgentCheck) monitors for missing replies
2238
+ // and nudges agents to send summaries. No action needed here.
2239
+
2240
+ this.emitWorkspaceStatus();
2241
+ this.checkWorkspaceComplete?.();
2242
+ }
2243
+
2244
+ private broadcastCompletion(completedAgentId: string, causedBy?: BusMessage['causedBy']): void {
2245
+ const completed = this.agents.get(completedAgentId);
2246
+ if (!completed) return;
2247
+
2248
+ const completedLabel = completed.config.label;
2249
+ const files = completed.state.artifacts.filter(a => a.path).map(a => a.path!);
2250
+ const summary = completed.state.history
2251
+ .filter(h => h.subtype === 'final_summary' || h.subtype === 'step_summary')
2252
+ .slice(-1)[0]?.content || '';
2253
+
2254
+ // Keep notification concise — agent can read files/git diff for details
2255
+ const shortSummary = summary.split('\n')[0]?.slice(0, 100) || '';
2256
+ const content = files.length > 0
2257
+ ? `${completedLabel} completed: ${files.length} files changed.${shortSummary ? ' ' + shortSummary : ''} Run \`git diff --stat HEAD~1\` for details.`
2258
+ : `${completedLabel} completed.${shortSummary ? ' ' + shortSummary : ''}`;
2259
+
2260
+ // Find all downstream agents — skip if already sent upstream_complete recently (60s)
2261
+ const now = Date.now();
2262
+
2263
+ // Pre-scan log once: build dedup set and pending-to-complete list
2264
+ const recentSentTo = new Set<string>(); // agentIds that received upstream_complete within 60s
2265
+ const pendingToComplete: { m: any; to: string }[] = [];
2266
+ for (const m of this.bus.getLog()) {
2267
+ if (m.from !== completedAgentId || m.payload?.action !== 'upstream_complete') continue;
2268
+ if (now - m.timestamp < 60_000) recentSentTo.add(m.to);
2269
+ if (m.status === 'pending') pendingToComplete.push({ m, to: m.to });
2270
+ }
2271
+
2272
+ let sent = 0;
2273
+ for (const [id, entry] of this.agents) {
2274
+ if (id === completedAgentId) continue;
2275
+ if (entry.config.type === 'input') continue;
2276
+ if (!entry.config.dependsOn.includes(completedAgentId)) continue;
2277
+
2278
+ // Dedup: skip if upstream_complete was sent to this target within last 60s
2279
+ if (recentSentTo.has(id)) {
2280
+ console.log(`[bus] ${completedLabel} → ${entry.config.label}: upstream_complete skipped (sent <60s ago)`);
2281
+ continue;
2282
+ }
2283
+
2284
+ // Merge: auto-complete older pending upstream_complete from same sender to this target
2285
+ for (const { m, to } of pendingToComplete) {
2286
+ if (to === id) {
2287
+ m.status = 'done' as any;
2288
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'done' } as any);
2289
+ }
2290
+ }
2291
+
2292
+ this.bus.send(completedAgentId, id, 'notify', {
2293
+ action: 'upstream_complete',
2294
+ content,
2295
+ files,
2296
+ }, { category: 'notification', causedBy });
2297
+ sent++;
2298
+ console.log(`[bus] ${completedLabel} → ${entry.config.label}: upstream_complete (${files.length} files)`);
2299
+ }
2300
+
2301
+ if (sent === 0) {
2302
+ console.log(`[bus] ${completedLabel} completed — no downstream agents`);
2303
+ }
2304
+ }
2305
+
2306
+ // ─── Agent liveness ─────────────────────────────────────
2307
+
2308
+ /** Find an active tmux session for an agent by checking naming conventions */
2309
+ // ─── Persistent Terminal Sessions ────────────────────────
2310
+
2311
+ /** Resolve the CLI session directory for a given project path */
2312
+ private getCliSessionDir(workDir?: string): string {
2313
+ const projectPath = workDir && workDir !== './' && workDir !== '.'
2314
+ ? join(this.projectPath, workDir) : this.projectPath;
2315
+ // Claude Code encodes paths by replacing all non-alphanumeric chars with '-'
2316
+ const encoded = resolve(projectPath).replace(/[^a-zA-Z0-9]/g, '-');
2317
+ return join(homedir(), '.claude', 'projects', encoded);
2318
+ }
2319
+
2320
+ /** Return the latest session ID (by mtime) from the CLI session dir, or undefined if none. */
2321
+ private getLatestSessionId(workDir?: string): string | undefined {
2322
+ try {
2323
+ const sessionDir = this.getCliSessionDir(workDir);
2324
+ if (!existsSync(sessionDir)) return undefined;
2325
+ const files = readdirSync(sessionDir).filter(f => f.endsWith('.jsonl'));
2326
+ if (files.length === 0) return undefined;
2327
+ const latest = files
2328
+ .map(f => ({ name: f, mtime: statSync(join(sessionDir, f)).mtimeMs }))
2329
+ .sort((a, b) => b.mtime - a.mtime)[0];
2330
+ return latest.name.replace('.jsonl', '');
2331
+ } catch {
2332
+ return undefined;
2333
+ }
2334
+ }
2335
+
2336
+ /** Lightweight session bind for non-persistentSession agents.
2337
+ * Checks if the tmux session already exists and sets entry.state.tmuxSession.
2338
+ * Also auto-binds boundSessionId from the latest session file if not already set.
2339
+ * Does NOT create any session or run any launch script.
2340
+ */
2341
+ private tryBindExistingSession(agentId: string, config: WorkspaceAgentConfig): void {
2342
+ const entry = this.agents.get(agentId);
2343
+ if (!entry) return;
2344
+
2345
+ const safeName = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').slice(0, 20);
2346
+ const sessionName = `mw-forge-${safeName(this.projectName)}-${safeName(config.label)}`;
2347
+
2348
+ // Check if tmux session is alive → set tmuxSession so open_terminal can return it
2349
+ try {
2350
+ execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`, { timeout: 3000 });
2351
+ if (entry.state.tmuxSession !== sessionName) {
2352
+ entry.state.tmuxSession = sessionName;
2353
+ this.saveNow();
2354
+ console.log(`[daemon] ${config.label}: found existing tmux session, bound tmuxSession`);
2355
+ }
2356
+ } catch {
2357
+ // No existing session — leave tmuxSession undefined, open_terminal will let FloatingTerminal create one
2358
+ }
2359
+
2360
+ // Auto-bind boundSessionId from latest session file if not already set
2361
+ if (!config.boundSessionId) {
2362
+ const sessionId = this.getLatestSessionId(config.workDir);
2363
+ if (sessionId) {
2364
+ config.boundSessionId = sessionId;
2365
+ this.saveNow();
2366
+ console.log(`[daemon] ${config.label}: auto-bound boundSessionId=${sessionId}`);
2367
+ }
2368
+ }
2369
+ }
2370
+
2371
+ /**
2372
+ * Create or attach to the tmux session for an agent (terminal-open path).
2373
+ * Unlike ensurePersistentSession, skips the 3s startup verification so the
2374
+ * HTTP response is fast. Returns the session name, or null on failure.
2375
+ */
2376
+ async openTerminalSession(agentId: string, forceRestart = false): Promise<string | null> {
2377
+ const entry = this.agents.get(agentId);
2378
+ if (!entry || entry.config.type === 'input') return null;
2379
+ const config = entry.config;
2380
+
2381
+ const safeName = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').slice(0, 20);
2382
+ const sessionName = `mw-forge-${safeName(this.projectName)}-${safeName(config.label)}`;
2383
+
2384
+ if (forceRestart) {
2385
+ // Kill existing tmux session so ensurePersistentSession rewrites the launch script
2386
+ // with the current boundSessionId (--resume flag). Safe — claude session data is in jsonl files.
2387
+ try { execSync(`tmux kill-session -t "${sessionName}" 2>/dev/null`, { timeout: 3000 }); } catch {}
2388
+ entry.state.tmuxSession = undefined;
2389
+ } else if (entry.state.tmuxSession) {
2390
+ // Attach to existing session if still alive
2391
+ try {
2392
+ execSync(`tmux has-session -t "${entry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 });
2393
+ return entry.state.tmuxSession;
2394
+ } catch {
2395
+ entry.state.tmuxSession = undefined;
2396
+ }
2397
+ }
2398
+
2399
+ // Create (or recreate) session without startup verification delay
2400
+ await this.ensurePersistentSession(agentId, config, true);
2401
+ return entry.state.tmuxSession || null;
2402
+ }
2403
+
2404
+ /** Create a persistent tmux session with the CLI agent */
2405
+ private async ensurePersistentSession(agentId: string, config: WorkspaceAgentConfig, skipStartupCheck = false): Promise<void> {
2406
+ const safeName = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').slice(0, 20);
2407
+ const sessionName = `mw-forge-${safeName(this.projectName)}-${safeName(config.label)}`;
2408
+
2409
+ // Pre-flight: check project's .claude/settings.json is valid (cached by mtime)
2410
+ const workDir = config.workDir && config.workDir !== './' && config.workDir !== '.'
2411
+ ? `${this.projectPath}/${config.workDir}` : this.projectPath;
2412
+ const projectSettingsFile = join(workDir, '.claude', 'settings.json');
2413
+ if (existsSync(projectSettingsFile)) {
2414
+ try {
2415
+ const mtime = statSync(projectSettingsFile).mtimeMs;
2416
+ if (this.settingsValidCache.get(projectSettingsFile) !== mtime) {
2417
+ const raw = readFileSync(projectSettingsFile, 'utf-8');
2418
+ JSON.parse(raw);
2419
+ this.settingsValidCache.set(projectSettingsFile, mtime);
2420
+ }
2421
+ } catch (err: any) {
2422
+ this.settingsValidCache.delete(projectSettingsFile);
2423
+ const errorMsg = `Invalid .claude/settings.json: ${err.message}`;
2424
+ console.error(`[daemon] ${config.label}: ${errorMsg}`);
2425
+ const entry = this.agents.get(agentId);
2426
+ if (entry) {
2427
+ entry.state.error = errorMsg;
2428
+ entry.state.smithStatus = 'down';
2429
+ this.emit('event', { type: 'smith_status', agentId, smithStatus: 'down' } as any);
2430
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'error', content: `⚠️ ${errorMsg}`, timestamp: new Date().toISOString() } } as any);
2431
+ this.emitAgentsChanged();
2432
+ }
2433
+ return;
2434
+ }
2435
+ }
2436
+
2437
+ // Write agent context file for hooks to read (workDir/.forge/agent-context.json)
2438
+ try {
2439
+ const forgeDir = join(workDir, '.forge');
2440
+ mkdirSync(forgeDir, { recursive: true });
2441
+ const ctxPath = join(forgeDir, 'agent-context.json');
2442
+ writeFileSync(ctxPath, JSON.stringify({
2443
+ workspaceId: this.workspaceId,
2444
+ agentId: config.id,
2445
+ agentLabel: config.label,
2446
+ forgePort: Number(process.env.PORT) || 8403,
2447
+ }, null, 2));
2448
+ console.log(`[daemon] ${config.label}: wrote agent-context.json to ${ctxPath}`);
2449
+ } catch (err: any) {
2450
+ console.error(`[daemon] ${config.label}: failed to write agent-context.json: ${err.message}`);
2451
+ }
2452
+
2453
+ // Check if tmux session already exists and Claude is still alive inside
2454
+ let sessionAlreadyExists = false;
2455
+ let tmuxSessionExists = false;
2456
+ console.log(`[daemon] ${config.label}: ensurePersistentSession called — sessionName=${sessionName} boundSessionId=${config.boundSessionId || 'NONE'} skipStartupCheck=${skipStartupCheck}`);
2457
+ try {
2458
+ execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`, { timeout: 3000 });
2459
+ tmuxSessionExists = true;
2460
+ } catch {}
2461
+ console.log(`[daemon] ${config.label}: tmuxSessionExists=${tmuxSessionExists}`);
2462
+
2463
+ if (tmuxSessionExists) {
2464
+ // Check if Claude process is still alive inside the tmux pane
2465
+ let claudeAlive = true;
2466
+ try {
2467
+ const paneContent = execSync(`tmux capture-pane -t "${sessionName}" -p -S -5`, { timeout: 3000, encoding: 'utf-8' });
2468
+ const exitedPatterns = [/^\$\s*$/, /\$ $/m, /Process exited/i, /command not found/i];
2469
+ if (exitedPatterns.some(p => p.test(paneContent))) {
2470
+ console.log(`[daemon] ${config.label}: Claude appears to have exited, recreating session`);
2471
+ try { execSync(`tmux kill-session -t "${sessionName}" 2>/dev/null`, { timeout: 3000 }); } catch {}
2472
+ claudeAlive = false;
2473
+ }
2474
+ } catch {
2475
+ // pane capture failed — assume alive
2476
+ }
2477
+
2478
+ if (claudeAlive) {
2479
+ sessionAlreadyExists = true;
2480
+ console.log(`[daemon] ${config.label}: persistent session alive (${sessionName}) — skipping script generation`);
2481
+ // Ensure FORGE env vars are set in the tmux session environment
2482
+ try {
2483
+ execSync(`tmux set-environment -t "${sessionName}" FORGE_WORKSPACE_ID "${this.workspaceId}" && tmux set-environment -t "${sessionName}" FORGE_AGENT_ID "${config.id}" && tmux set-environment -t "${sessionName}" FORGE_PORT "${Number(process.env.PORT) || 8403}"`, { timeout: 5000 });
2484
+ } catch {}
2485
+ }
2486
+ }
2487
+
2488
+ if (!sessionAlreadyExists) {
2489
+ // Pre-bind: find existing session file BEFORE starting CLI so --resume is available from the start.
2490
+ // This avoids starting a fresh CLI then restarting it after polling finds the session.
2491
+ if (!config.primary && !config.boundSessionId) {
2492
+ const existingSessionId = this.getLatestSessionId(config.workDir);
2493
+ if (existingSessionId) {
2494
+ config.boundSessionId = existingSessionId;
2495
+ this.saveNow();
2496
+ console.log(`[daemon] ${config.label}: pre-bound to existing session ${existingSessionId}`);
2497
+ }
2498
+ }
2499
+
2500
+ // Create new tmux session and start the CLI agent
2501
+ try {
2502
+ // Resolve agent launch info
2503
+ let cliCmd = 'claude';
2504
+ let cliType = 'claude-code';
2505
+ let supportsSession = true;
2506
+ let skipPermissionsFlag = '--dangerously-skip-permissions';
2507
+ let envExports = '';
2508
+ let modelFlag = '';
2509
+ try {
2510
+ const { resolveTerminalLaunch, listAgents } = await import('../agents/index') as any;
2511
+ const info = resolveTerminalLaunch(config.agentId);
2512
+ cliCmd = info.cliCmd || 'claude';
2513
+ cliType = info.cliType || 'claude-code';
2514
+ supportsSession = info.supportsSession ?? true;
2515
+ const agents = listAgents();
2516
+ const agentDef = agents.find((a: any) => a.id === config.agentId);
2517
+ if (agentDef?.skipPermissionsFlag) skipPermissionsFlag = agentDef.skipPermissionsFlag;
2518
+ if (info.env) {
2519
+ envExports = Object.entries(info.env)
2520
+ .filter(([k]) => k !== 'CLAUDE_MODEL')
2521
+ .map(([k, v]) => `export ${k}="${v}"`)
2522
+ .join(' && ');
2523
+ if (envExports) envExports += ' && ';
2524
+ }
2525
+ // Workspace agent model takes priority over profile/settings model
2526
+ const effectiveModel = config.model || info.model;
2527
+ if (effectiveModel) modelFlag = ` --model ${effectiveModel}`;
2528
+ } catch {}
2529
+
2530
+ // Generate MCP config for Claude Code agents
2531
+ let mcpConfigFlag = '';
2532
+ if (cliType === 'claude-code') {
2533
+ try {
2534
+ const mcpPort = Number(process.env.MCP_PORT) || 8406;
2535
+ const mcpConfigPath = join(workDir, '.forge', 'mcp.json');
2536
+ const mcpConfig = {
2537
+ mcpServers: {
2538
+ forge: {
2539
+ type: 'sse',
2540
+ url: `http://localhost:${mcpPort}/sse?workspaceId=${this.workspaceId}&agentId=${config.id}`,
2541
+ },
2542
+ },
2543
+ };
2544
+ mkdirSync(join(workDir, '.forge'), { recursive: true });
2545
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
2546
+ mcpConfigFlag = ` --mcp-config "${mcpConfigPath}"`;
2547
+ } catch (err: any) {
2548
+ console.log(`[daemon] ${config.label}: MCP config generation failed: ${err.message}`);
2549
+ }
2550
+ }
2551
+
2552
+ execSync(`tmux new-session -d -s "${sessionName}" -c "${workDir}"`, { timeout: 5000 });
2553
+
2554
+ // Build launch script to avoid tmux send-keys truncation
2555
+ const scriptLines: string[] = ['#!/bin/bash', `cd "${workDir}"`];
2556
+
2557
+ // Unset old profile vars
2558
+ scriptLines.push('unset ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_SMALL_FAST_MODEL CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC DISABLE_TELEMETRY DISABLE_ERROR_REPORTING DISABLE_AUTOUPDATER DISABLE_NON_ESSENTIAL_MODEL_CALLS CLAUDE_MODEL');
2559
+
2560
+ // Set FORGE env vars
2561
+ scriptLines.push(`export FORGE_WORKSPACE_ID="${this.workspaceId}" FORGE_AGENT_ID="${config.id}" FORGE_PORT="${Number(process.env.PORT) || 8403}"`);
2562
+
2563
+ // Set profile env vars
2564
+ if (envExports) {
2565
+ scriptLines.push(envExports.replace(/ && /g, '\n').replace(/\n$/, ''));
2566
+ }
2567
+
2568
+ // Build CLI command
2569
+ let cmd = cliCmd;
2570
+ if (supportsSession) {
2571
+ let sessionId: string | undefined;
2572
+ if (config.primary) {
2573
+ sessionId = getFixedSession(this.projectPath);
2574
+ console.log(`[daemon] ${config.label}: fixedSession=${sessionId || 'NONE'} for ${this.projectPath}`);
2575
+ } else {
2576
+ sessionId = config.boundSessionId;
2577
+ console.log(`[daemon] ${config.label}: script-gen boundSessionId=${sessionId || 'NONE'}`);
2578
+ }
2579
+ if (sessionId) {
2580
+ const sessionFile = join(this.getCliSessionDir(config.workDir), `${sessionId}.jsonl`);
2581
+ if (existsSync(sessionFile)) {
2582
+ cmd += ` --resume ${sessionId}`;
2583
+ console.log(`[daemon] ${config.label}: script-gen adding --resume ${sessionId}`);
2584
+ } else {
2585
+ console.log(`[daemon] ${config.label}: bound session ${sessionId} missing, starting fresh`);
2586
+ }
2587
+ } else {
2588
+ console.log(`[daemon] ${config.label}: script-gen no boundSessionId → no --resume (skipStartupCheck=${skipStartupCheck})`);
2589
+ }
2590
+ }
2591
+ if (modelFlag) cmd += modelFlag;
2592
+ if (config.skipPermissions !== false && skipPermissionsFlag) cmd += ` ${skipPermissionsFlag}`;
2593
+ if (mcpConfigFlag) cmd += mcpConfigFlag;
2594
+ scriptLines.push(`exec ${cmd}`);
2595
+
2596
+ // Write script and execute in tmux
2597
+ const scriptPath = `/tmp/forge-launch-${config.id.replace(/[^a-z0-9-]/g, '')}.sh`;
2598
+ console.log(`[daemon] ${config.label}: writing launch script ${scriptPath}`);
2599
+ console.log(`[daemon] ${config.label}: exec line → ${cmd}`);
2600
+ writeFileSync(scriptPath, scriptLines.join('\n'), { mode: 0o755 });
2601
+ execSync(`tmux send-keys -t "${sessionName}" 'bash ${scriptPath}' Enter`, { timeout: 5000 });
2602
+
2603
+ console.log(`[daemon] ${config.label}: persistent session created (${sessionName}) [${cliType}: ${cliCmd}]`);
2604
+
2605
+ // Verify CLI started successfully (check after 3s if process is still alive)
2606
+ // Skip when called from openTerminalSession (terminal-open path) for fast response.
2607
+ if (skipStartupCheck) {
2608
+ // Set tmuxSession here only — normal path sets it after startup verification passes.
2609
+ const entrySkip = this.agents.get(agentId);
2610
+ if (entrySkip) {
2611
+ entrySkip.state.tmuxSession = sessionName;
2612
+ this.saveNow();
2613
+ this.emitAgentsChanged();
2614
+ }
2615
+ // Fire boundSessionId binding in background (no await — don't block terminal open)
2616
+ if (!config.primary && !config.boundSessionId) {
2617
+ const bgScriptPath = `/tmp/forge-launch-${config.id.replace(/[^a-z0-9-]/g, '')}.sh`;
2618
+ setTimeout(() => {
2619
+ const sid = this.getLatestSessionId(config.workDir);
2620
+ if (sid) {
2621
+ config.boundSessionId = sid;
2622
+ this.saveNow();
2623
+ console.log(`[daemon] ${config.label}: background bound to session ${sid}`);
2624
+ // Also update launch script for future restarts
2625
+ if (existsSync(bgScriptPath)) {
2626
+ try {
2627
+ const lines = readFileSync(bgScriptPath, 'utf-8').split('\n');
2628
+ const execIdx = lines.findIndex(l => l.startsWith('exec '));
2629
+ if (execIdx >= 0) {
2630
+ const withoutResume = lines[execIdx].replace(/\s--resume\s+\S+/, '');
2631
+ const afterExec = withoutResume.startsWith('exec ') ? 5 : 0;
2632
+ const cmdEnd = withoutResume.indexOf(' ', afterExec);
2633
+ lines[execIdx] = cmdEnd >= 0
2634
+ ? withoutResume.slice(0, cmdEnd) + ` --resume ${sid}` + withoutResume.slice(cmdEnd)
2635
+ : withoutResume + ` --resume ${sid}`;
2636
+ writeFileSync(bgScriptPath, lines.join('\n'), { mode: 0o755 });
2637
+ console.log(`[daemon] ${config.label}: background updated launch script with --resume ${sid}`);
2638
+ }
2639
+ } catch {}
2640
+ }
2641
+ }
2642
+ }, 5000);
2643
+ }
2644
+ return;
2645
+ }
2646
+ await new Promise(resolve => setTimeout(resolve, 3000));
2647
+ try {
2648
+ const paneContent = execSync(`tmux capture-pane -t "${sessionName}" -p -S -20`, { timeout: 3000, encoding: 'utf-8' });
2649
+ // Check for common startup errors
2650
+ const errorPatterns = [
2651
+ /error.*settings\.json/i,
2652
+ /invalid.*json/i,
2653
+ /SyntaxError/i,
2654
+ /ENOENT.*settings/i,
2655
+ /failed to parse/i,
2656
+ /could not read/i,
2657
+ /fatal/i,
2658
+ /No conversation found/i,
2659
+ /could not connect/i,
2660
+ /ECONNREFUSED/i,
2661
+ ];
2662
+ const hasError = errorPatterns.some(p => p.test(paneContent));
2663
+ if (hasError) {
2664
+ const errorLines = paneContent.split('\n').filter(l => /error|invalid|syntax|fatal|failed|No conversation|ECONNREFUSED/i.test(l)).slice(0, 3);
2665
+ const errorMsg = errorLines.join(' ').slice(0, 200) || 'CLI failed to start (check project settings)';
2666
+ console.error(`[daemon] ${config.label}: CLI startup error detected: ${errorMsg}`);
2667
+
2668
+ const entry = this.agents.get(agentId);
2669
+ if (entry) {
2670
+ entry.state.error = `Terminal failed: ${errorMsg}. Falling back to headless mode.`;
2671
+ entry.state.tmuxSession = undefined; // clear so message loop uses headless (claude -p)
2672
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'error', content: `Terminal startup failed: ${errorMsg}. Auto-fallback to headless.`, timestamp: new Date().toISOString() } } as any);
2673
+ this.emitAgentsChanged();
2674
+ }
2675
+ // Kill the failed tmux session
2676
+ try { execSync(`tmux kill-session -t "${sessionName}" 2>/dev/null`, { timeout: 3000 }); } catch {}
2677
+ return;
2678
+ }
2679
+ } catch {}
2680
+ } catch (err: any) {
2681
+ console.error(`[daemon] ${config.label}: failed to create persistent session: ${err.message}`);
2682
+ const entry = this.agents.get(agentId);
2683
+ if (entry) {
2684
+ entry.state.error = `Failed to create terminal: ${err.message}`;
2685
+ entry.state.smithStatus = 'down';
2686
+ this.emit('event', { type: 'smith_status', agentId, smithStatus: 'down' } as any);
2687
+ this.emitAgentsChanged();
2688
+ }
2689
+ return;
2690
+ }
2691
+ }
2692
+
2693
+ // Store tmux session name in agent state
2694
+ const entry = this.agents.get(agentId);
2695
+ if (entry) {
2696
+ entry.state.tmuxSession = sessionName;
2697
+ this.saveNow();
2698
+ this.emitAgentsChanged();
2699
+ }
2700
+
2701
+ // Ensure boundSessionId is set before returning (required for session monitor + --resume)
2702
+ // Also re-bind if existing boundSessionId points to a deleted session file
2703
+ if (!config.primary && config.boundSessionId) {
2704
+ const boundFile = join(this.getCliSessionDir(config.workDir), `${config.boundSessionId}.jsonl`);
2705
+ if (!existsSync(boundFile)) {
2706
+ console.log(`[daemon] ${config.label}: boundSession ${config.boundSessionId} file missing, re-binding`);
2707
+ config.boundSessionId = undefined;
2708
+ }
2709
+ }
2710
+ if (!config.primary && !config.boundSessionId) {
2711
+ const pollStart = Date.now();
2712
+ const pollDelay = sessionAlreadyExists ? 500 : 2000;
2713
+ await new Promise<void>(resolve => {
2714
+ const attempt = () => {
2715
+ if (!this.daemonActive) { resolve(); return; }
2716
+ const sessionId = this.getLatestSessionId(config.workDir);
2717
+ if (sessionId) {
2718
+ config.boundSessionId = sessionId;
2719
+ this.saveNow();
2720
+ console.log(`[daemon] ${config.label}: bound to session ${config.boundSessionId}`);
2721
+ // Update launch script with the now-known sessionId — script was written before
2722
+ // polling completed so it had no --resume flag. Fix it for future restarts.
2723
+ const scriptPath = `/tmp/forge-launch-${config.id.replace(/[^a-z0-9-]/g, '')}.sh`;
2724
+ if (existsSync(scriptPath)) {
2725
+ try {
2726
+ const lines = readFileSync(scriptPath, 'utf-8').split('\n');
2727
+ const execIdx = lines.findIndex(l => l.startsWith('exec '));
2728
+ if (execIdx >= 0) {
2729
+ // Remove any existing --resume flag, then re-insert after command name.
2730
+ // Line format: 'exec <cmd> [args...]'
2731
+ // Insert after cmd (skip 'exec ' prefix + cmd word) so bash doesn't
2732
+ // misinterpret --resume as an exec builtin option.
2733
+ const withoutResume = lines[execIdx].replace(/\s--resume\s+\S+/, '');
2734
+ const afterExec = withoutResume.startsWith('exec ') ? 5 : 0;
2735
+ const cmdEnd = withoutResume.indexOf(' ', afterExec);
2736
+ lines[execIdx] = cmdEnd >= 0
2737
+ ? withoutResume.slice(0, cmdEnd) + ` --resume ${sessionId}` + withoutResume.slice(cmdEnd)
2738
+ : withoutResume + ` --resume ${sessionId}`;
2739
+ writeFileSync(scriptPath, lines.join('\n'), { mode: 0o755 });
2740
+ console.log(`[daemon] ${config.label}: updated launch script with --resume ${sessionId}`);
2741
+ }
2742
+ } catch {}
2743
+ }
2744
+ return resolve();
2745
+ }
2746
+ if (Date.now() - pollStart < 10_000) {
2747
+ setTimeout(attempt, 1000);
2748
+ } else {
2749
+ console.log(`[daemon] ${config.label}: no session file after 10s, skipping bind`);
2750
+ const entry = this.agents.get(agentId);
2751
+ if (entry) {
2752
+ entry.state.error = 'Terminal session not ready — click "Open Terminal" to start it manually';
2753
+ this.emit('event', { type: 'smith_status', agentId, smithStatus: entry.state.smithStatus } as any);
2754
+ this.emitAgentsChanged();
2755
+ }
2756
+ resolve();
2757
+ }
2758
+ };
2759
+ setTimeout(attempt, pollDelay);
2760
+ });
2761
+ }
2762
+ }
2763
+
2764
+ /** Inject text into an agent's persistent terminal session */
2765
+ injectIntoSession(agentId: string, text: string): boolean {
2766
+ const entry = this.agents.get(agentId);
2767
+ // Verify stored session is alive
2768
+ if (entry?.state.tmuxSession) {
2769
+ try { execSync(`tmux has-session -t "${entry.state.tmuxSession}" 2>/dev/null`, { timeout: 3000 }); }
2770
+ catch { entry.state.tmuxSession = undefined; }
2771
+ }
2772
+ const tmuxSession = entry?.state.tmuxSession || this.findTmuxSession(entry?.config.label || '');
2773
+ if (!tmuxSession) return false;
2774
+ // Cache found session for future use
2775
+ if (entry && !entry.state.tmuxSession) entry.state.tmuxSession = tmuxSession;
2776
+
2777
+ try {
2778
+ const tmpFile = `/tmp/forge-inject-${Date.now()}.txt`;
2779
+ writeFileSync(tmpFile, text);
2780
+ execSync(`tmux load-buffer ${tmpFile}`, { timeout: 5000 });
2781
+ execSync(`tmux paste-buffer -t "${tmuxSession}" && sleep 0.2 && tmux send-keys -t "${tmuxSession}" Enter`, { timeout: 5000 });
2782
+ try { unlinkSync(tmpFile); } catch {}
2783
+ return true;
2784
+ } catch (err: any) {
2785
+ console.error(`[inject] Failed for ${tmuxSession}: ${err.message}`);
2786
+ return false;
2787
+ }
2788
+ }
2789
+
2790
+ /** Check if agent has a persistent session available */
2791
+ hasPersistentSession(agentId: string): boolean {
2792
+ const entry = this.agents.get(agentId);
2793
+ if (!entry) return false;
2794
+ if (entry.state.tmuxSession) return true;
2795
+ return !!this.findTmuxSession(entry.config.label);
2796
+ }
2797
+
2798
+ private findTmuxSession(agentLabel: string): string | null {
2799
+ const safeName = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').slice(0, 20);
2800
+ const projectSafe = safeName(this.projectName);
2801
+ const agentSafe = safeName(agentLabel);
2802
+
2803
+ // Try workspace naming: mw-forge-{project}-{agent}
2804
+ const wsName = `mw-forge-${projectSafe}-${agentSafe}`;
2805
+ try { execSync(`tmux has-session -t "${wsName}" 2>/dev/null`, { timeout: 3000 }); return wsName; } catch {}
2806
+
2807
+ // Try VibeCoding naming: mw-{project}
2808
+ const vcName = `mw-${projectSafe}`;
2809
+ try { execSync(`tmux has-session -t "${vcName}" 2>/dev/null`, { timeout: 3000 }); return vcName; } catch {}
2810
+
2811
+ // Search terminal-state.json for project matching tmux session
2812
+ try {
2813
+ const statePath = join(homedir(), '.forge', 'data', 'terminal-state.json');
2814
+ if (existsSync(statePath)) {
2815
+ const termState = JSON.parse(readFileSync(statePath, 'utf-8'));
2816
+ for (const tab of termState.tabs || []) {
2817
+ if (tab.projectPath === this.projectPath) {
2818
+ const findSession = (tree: any): string | null => {
2819
+ if (tree?.type === 'terminal' && tree.sessionName) return tree.sessionName;
2820
+ for (const child of tree?.children || []) {
2821
+ const found = findSession(child);
2822
+ if (found) return found;
2823
+ }
2824
+ return null;
2825
+ };
2826
+ const sess = findSession(tab.tree);
2827
+ if (sess) {
2828
+ try { execSync(`tmux has-session -t "${sess}" 2>/dev/null`, { timeout: 3000 }); return sess; } catch {}
2829
+ }
2830
+ }
2831
+ }
2832
+ }
2833
+ } catch {}
2834
+
2835
+ return null;
2836
+ }
2837
+
2838
+ private updateAgentLiveness(agentId: string): void {
2839
+ const entry = this.agents.get(agentId);
2840
+ if (!entry) {
2841
+ this.bus.setAgentStatus(agentId, 'down');
2842
+ return;
2843
+ }
2844
+ if (entry.state.taskStatus === 'running') this.bus.setAgentStatus(agentId, 'busy');
2845
+ else if (entry.state.smithStatus === 'active') this.bus.setAgentStatus(agentId, 'alive');
2846
+ else this.bus.setAgentStatus(agentId, 'down');
2847
+ }
2848
+
2849
+ // ─── Bus message handling ──────────────────────────────
2850
+
2851
+ private handleBusMessage(msg: BusMessage): void {
2852
+ // Dedup
2853
+ if (this.bus.isDuplicate(msg.id)) return;
2854
+
2855
+ // Emit to UI after dedup (no duplicates, no ACKs)
2856
+ this.emit('event', { type: 'bus_message', message: msg } satisfies OrchestratorEvent);
2857
+
2858
+ // Route to target
2859
+ this.routeMessageToAgent(msg.to, msg);
2860
+ this.checkWorkspaceComplete();
2861
+ }
2862
+
2863
+ private routeMessageToAgent(targetId: string, msg: BusMessage): void {
2864
+ const target = this.agents.get(targetId);
2865
+ if (!target) return;
2866
+
2867
+ const fromLabel = this.agents.get(msg.from)?.config.label || msg.from;
2868
+ const action = msg.payload.action;
2869
+ const content = msg.payload.content || '';
2870
+
2871
+ console.log(`[bus] ${fromLabel} → ${target.config.label}: ${action} "${content.slice(0, 80)}"`);
2872
+
2873
+ const logEntry = {
2874
+ type: 'system' as const,
2875
+ subtype: 'bus_message',
2876
+ content: `[From ${fromLabel}]: ${content || action}`,
2877
+ timestamp: new Date(msg.timestamp).toISOString(),
2878
+ };
2879
+
2880
+ // Helper: mark message as processed when actually consumed
2881
+ const ackAndDeliver = () => {
2882
+ msg.status = 'done';
2883
+ };
2884
+
2885
+ // ── Input node: request user input ──
2886
+ if (target.config.type === 'input') {
2887
+ if (action === 'info_request' || action === 'question') {
2888
+ ackAndDeliver();
2889
+ this.emit('event', {
2890
+ type: 'user_input_request',
2891
+ agentId: targetId,
2892
+ fromAgent: msg.from,
2893
+ question: content,
2894
+ } satisfies OrchestratorEvent);
2895
+ }
2896
+ return;
2897
+ }
2898
+
2899
+ // ── Store message in agent history ──
2900
+ target.state.history.push(logEntry);
2901
+
2902
+ // ── requiresApproval → set pending_approval on arrival ──
2903
+ if (target.config.requiresApproval) {
2904
+ msg.status = 'pending_approval';
2905
+ this.emit('event', { type: 'bus_message_status', messageId: msg.id, status: 'pending_approval' } as any);
2906
+ console.log(`[bus] ${target.config.label}: received ${action} — pending approval`);
2907
+ return;
2908
+ }
2909
+
2910
+ // ── Message stays pending — message loop will consume it when smith is ready ──
2911
+ console.log(`[bus] ${target.config.label}: received ${action} — queued in inbox (${msg.status})`);
2912
+ }
2913
+
2914
+ // ─── Message consumption loop ─────────────────────────
2915
+ private messageLoopTimers = new Map<string, NodeJS.Timeout>();
2916
+
2917
+ /** Start the message consumption loop for a smith */
2918
+ private startMessageLoop(agentId: string): void {
2919
+ if (this.messageLoopTimers.has(agentId)) return; // already running
2920
+
2921
+ let debugTick = 0;
2922
+ const tick = () => {
2923
+ const entry = this.agents.get(agentId);
2924
+ if (!entry) {
2925
+ this.stopMessageLoop(agentId);
2926
+ return;
2927
+ }
2928
+
2929
+ // Don't stop loop if smith is down — just skip this tick
2930
+ // (loop stays alive so it works when smith comes back)
2931
+ if (entry.state.smithStatus !== 'active') return;
2932
+
2933
+ // Skip if already busy
2934
+ if (entry.state.taskStatus === 'running') return;
2935
+
2936
+ // Skip if any message is already running for this agent (O(1) cache lookup)
2937
+ if (this.agentRunningMsg.has(agentId)) return;
2938
+
2939
+ // Execution path determined by config, not runtime tmux state
2940
+ const isTerminalMode = entry.config.persistentSession;
2941
+ if (isTerminalMode) {
2942
+ // Terminal mode: need tmux session. If missing, skip this tick (health check will restart it)
2943
+ if (!entry.state.tmuxSession) {
2944
+ if (++debugTick % 15 === 0) {
2945
+ console.log(`[inbox] ${entry.config.label}: terminal mode but no tmux session — waiting for auto-restart`);
2946
+ }
2947
+ return;
2948
+ }
2949
+ } else {
2950
+ // Headless mode: need worker ready
2951
+ if (!entry.worker) {
2952
+ if (this.daemonActive) {
2953
+ console.log(`[inbox] ${entry.config.label}: no worker, recreating...`);
2954
+ this.enterDaemonListening(agentId);
2955
+ }
2956
+ return;
2957
+ }
2958
+ if (!entry.worker.isListening()) {
2959
+ if (++debugTick % 15 === 0) {
2960
+ console.log(`[inbox] ${entry.config.label}: not listening (smith=${entry.state.smithStatus} task=${entry.state.taskStatus})`);
2961
+ }
2962
+ return;
2963
+ }
2964
+ }
2965
+
2966
+ // requiresApproval is handled at message arrival time (routeMessageToAgent),
2967
+ // not in the message loop. Approved messages come through as normal 'pending'.
2968
+
2969
+ // Dedup: if multiple upstream_complete from same sender are pending, keep only latest
2970
+ const allRaw = this.bus.getPendingMessagesFor(agentId).filter(m => m.from !== agentId && m.type !== 'ack');
2971
+ const upstreamSeen = new Set<string>();
2972
+ for (let i = allRaw.length - 1; i >= 0; i--) {
2973
+ const m = allRaw[i];
2974
+ if (m.payload?.action === 'upstream_complete') {
2975
+ const key = `upstream-${m.from}`;
2976
+ if (upstreamSeen.has(key)) {
2977
+ m.status = 'done' as any;
2978
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'done' } as any);
2979
+ }
2980
+ upstreamSeen.add(key);
2981
+ }
2982
+ }
2983
+
2984
+ // Find next pending message, applying causedBy rules
2985
+ const allPending = allRaw.filter(m => m.status === 'pending');
2986
+ const pending = allPending.filter(m => {
2987
+ // Tickets: accepted but check retry limit
2988
+ if (m.category === 'ticket') {
2989
+ const maxRetries = m.maxRetries ?? 3;
2990
+ if ((m.ticketRetries || 0) >= maxRetries) {
2991
+ console.log(`[inbox] ${entry.config.label}: ticket ${m.id.slice(0, 8)} exceeded max retries (${maxRetries}), marking failed`);
2992
+ m.status = 'failed' as any;
2993
+ m.ticketStatus = 'closed';
2994
+ this.emit('event', { type: 'bus_message_status', messageId: m.id, status: 'failed' } as any);
2995
+ return false;
2996
+ }
2997
+ return true;
2998
+ }
2999
+
3000
+ // System messages (from _watch, _system, user) bypass causedBy rules
3001
+ if (m.from.startsWith('_') || m.from === 'user') return true;
3002
+
3003
+ // Notifications: check causedBy for loop prevention
3004
+ if (m.causedBy) {
3005
+ // Rule 1: Is this a response to something I sent? → accept (for verification)
3006
+ const myOutbox = this.bus.getOutboxFor(agentId);
3007
+ if (myOutbox.some(o => o.id === m.causedBy!.messageId)) return true;
3008
+
3009
+ // Rule 2: Notification from downstream → discard (prevents reverse flow)
3010
+ if (!this.isUpstream(m.from, agentId)) {
3011
+ console.log(`[inbox] ${entry.config.label}: discarding notification from downstream ${this.agents.get(m.from)?.config.label || m.from}`);
3012
+ m.status = 'done' as any; // silently consume
3013
+ return false;
3014
+ }
3015
+ }
3016
+
3017
+ // Default: accept (upstream notifications, no causedBy = initial trigger)
3018
+ return true;
3019
+ });
3020
+ if (pending.length === 0) return;
3021
+
3022
+ const nextMsg = pending[0];
3023
+ const fromLabel = this.agents.get(nextMsg.from)?.config.label || nextMsg.from;
3024
+ console.log(`[inbox] ${entry.config.label}: consuming message from ${fromLabel} (${nextMsg.payload.action})`);
3025
+
3026
+ // Mark message as running (being processed)
3027
+ nextMsg.status = 'running' as any;
3028
+ this.agentRunningMsg.set(agentId, nextMsg.id);
3029
+ this.emit('event', { type: 'bus_message_status', messageId: nextMsg.id, status: 'running' } as any);
3030
+
3031
+ const logEntry = {
3032
+ type: 'system' as const,
3033
+ subtype: 'bus_message',
3034
+ content: `[From ${fromLabel}]: ${nextMsg.payload.content || nextMsg.payload.action}`,
3035
+ timestamp: new Date(nextMsg.timestamp).toISOString(),
3036
+ };
3037
+
3038
+ // Terminal mode → inject; headless → worker (claude -p)
3039
+ if (isTerminalMode) {
3040
+ // Check if role reminder needed (combats auto-compaction over long sessions)
3041
+ let messageText = nextMsg.payload.content || nextMsg.payload.action;
3042
+ if (this.needsRoleReminder(agentId) && entry.config.role?.trim()) {
3043
+ messageText = this.buildRoleReminder(entry.config) + '\n\n' + messageText;
3044
+ this.markRoleInjected(agentId);
3045
+ console.log(`[inbox] ${entry.config.label}: prepended role reminder`);
3046
+ } else {
3047
+ this.incrementMsgCount(agentId);
3048
+ }
3049
+ const injected = this.injectIntoSession(agentId, messageText);
3050
+ if (injected) {
3051
+ entry.state.taskStatus = 'running';
3052
+ this.emit('event', { type: 'task_status', agentId, taskStatus: 'running' } as any);
3053
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'execution_method', content: '📺 Injected into terminal, monitoring for completion...', timestamp: new Date().toISOString() } } as any);
3054
+ console.log(`[inbox] ${entry.config.label}: injected into terminal, starting completion monitor`);
3055
+ entry.state.currentMessageId = nextMsg.id;
3056
+ this.monitorTerminalCompletion(agentId, nextMsg.id, entry.state.tmuxSession!);
3057
+ } else {
3058
+ // Terminal inject failed — clear dead session, message stays pending
3059
+ // Health check will auto-restart the terminal session
3060
+ entry.state.tmuxSession = undefined;
3061
+ nextMsg.status = 'pending' as any; // revert to pending for retry
3062
+ this.agentRunningMsg.delete(agentId);
3063
+ this.emit('event', { type: 'bus_message_status', messageId: nextMsg.id, status: 'pending' } as any);
3064
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'warning', content: '⚠️ Terminal session down — waiting for auto-restart, message will retry', timestamp: new Date().toISOString() } } as any);
3065
+ console.log(`[inbox] ${entry.config.label}: terminal inject failed, cleared session — waiting for health check restart`);
3066
+ this.emitAgentsChanged();
3067
+ }
3068
+ } else {
3069
+ entry.worker!.setProcessingMessage(nextMsg.id);
3070
+ entry.worker!.wake({ type: 'bus_message', messages: [logEntry] });
3071
+ this.emit('event', { type: 'log', agentId, entry: { type: 'system', subtype: 'execution_method', content: `⚡ Executed via headless (agent: ${entry.config.agentId || 'claude'})`, timestamp: new Date().toISOString() } } as any);
3072
+ }
3073
+ };
3074
+
3075
+ // Check every 2 seconds
3076
+ const timer = setInterval(tick, 2000);
3077
+ timer.unref(); // Don't prevent process exit in tests
3078
+ this.messageLoopTimers.set(agentId, timer);
3079
+ // Also run immediately
3080
+ tick();
3081
+ }
3082
+
3083
+ /** Stop the message consumption loop for a smith */
3084
+ private stopMessageLoop(agentId: string): void {
3085
+ const timer = this.messageLoopTimers.get(agentId);
3086
+ if (timer) {
3087
+ clearInterval(timer);
3088
+ this.messageLoopTimers.delete(agentId);
3089
+ }
3090
+ }
3091
+
3092
+ /** Stop all message loops */
3093
+ private stopAllMessageLoops(): void {
3094
+ for (const [id] of this.messageLoopTimers) {
3095
+ this.stopMessageLoop(id);
3096
+ }
3097
+ }
3098
+
3099
+ // ─── Terminal completion monitor ──────────────────────
3100
+ private terminalMonitors = new Map<string, NodeJS.Timeout>();
3101
+
3102
+ /**
3103
+ * Monitor a tmux session for completion after injecting a message.
3104
+ * Detects CLI prompt patterns (❯, $, >) indicating the agent is idle.
3105
+ * Requires 2 consecutive prompt detections (10s) to confirm completion.
3106
+ */
3107
+ private monitorTerminalCompletion(agentId: string, messageId: string, tmuxSession: string): void {
3108
+ // Stop any existing monitor for this agent
3109
+ const existing = this.terminalMonitors.get(agentId);
3110
+ if (existing) clearInterval(existing);
3111
+
3112
+ // Prompt patterns that indicate the CLI is idle and waiting for input
3113
+ // Claude Code: ❯ Codex: > Aider: > Generic shell: $ #
3114
+ const PROMPT_PATTERNS = [
3115
+ /^❯\s*$/, // Claude Code idle prompt
3116
+ /^>\s*$/, // Codex / generic prompt
3117
+ /^\$\s*$/, // Shell prompt
3118
+ /^#\s*$/, // Root shell prompt
3119
+ /^aider>\s*$/, // Aider prompt
3120
+ ];
3121
+
3122
+ let promptCount = 0;
3123
+ let started = false;
3124
+ const CONFIRM_CHECKS = 2; // 2 consecutive prompt detections = done
3125
+ const CHECK_INTERVAL = 5000; // 5s between checks
3126
+
3127
+ const timer = setInterval(() => {
3128
+ try {
3129
+ const output = execSync(`tmux capture-pane -t "${tmuxSession}" -p -S -30`, { timeout: 3000, encoding: 'utf-8' });
3130
+
3131
+ // Strip ANSI escape sequences for clean matching
3132
+ const clean = output.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
3133
+ // Get last few non-empty lines
3134
+ const lines = clean.split('\n').map(l => l.trim()).filter(Boolean);
3135
+ const tail = lines.slice(-5);
3136
+
3137
+ // First check: detect that agent started working (output changed from inject)
3138
+ if (!started && lines.length > 3) {
3139
+ started = true;
3140
+ }
3141
+ if (!started) return;
3142
+
3143
+ // Check if any of the last lines match a prompt pattern
3144
+ const hasPrompt = tail.some(line => PROMPT_PATTERNS.some(p => p.test(line)));
3145
+
3146
+ if (hasPrompt) {
3147
+ promptCount++;
3148
+ if (promptCount >= CONFIRM_CHECKS) {
3149
+ clearInterval(timer);
3150
+ this.terminalMonitors.delete(agentId);
3151
+ this.agentRunningMsg.delete(agentId);
3152
+
3153
+ // Extract output summary (skip prompt lines)
3154
+ const contentLines = lines.filter(l => !PROMPT_PATTERNS.some(p => p.test(l)));
3155
+ const summary = contentLines.slice(-15).join('\n');
3156
+
3157
+ // Mark message done
3158
+ const msg = this.bus.getLog().find(m => m.id === messageId);
3159
+ if (msg && msg.status !== 'done') {
3160
+ msg.status = 'done' as any;
3161
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'done' } as any);
3162
+ }
3163
+
3164
+ // Emit output to log panel
3165
+ this.emit('event', { type: 'log', agentId, entry: { type: 'assistant', subtype: 'terminal_output', content: `📺 Terminal completed:\n${summary.slice(0, 500)}`, timestamp: new Date().toISOString() } } as any);
3166
+
3167
+ // Trigger downstream notifications
3168
+ const entry = this.agents.get(agentId);
3169
+ if (entry) {
3170
+ entry.state.currentMessageId = undefined;
3171
+ this.handleAgentDone(agentId, entry, summary.slice(0, 300));
3172
+ }
3173
+ console.log(`[terminal-monitor] ${agentId}: prompt detected, completed`);
3174
+ }
3175
+ } else {
3176
+ promptCount = 0; // reset — still working
3177
+ }
3178
+ } catch {
3179
+ // Session died
3180
+ clearInterval(timer);
3181
+ this.terminalMonitors.delete(agentId);
3182
+ this.agentRunningMsg.delete(agentId);
3183
+ const msg = this.bus.getLog().find(m => m.id === messageId);
3184
+ if (msg && msg.status !== 'done' && msg.status !== 'failed') {
3185
+ msg.status = 'failed' as any;
3186
+ this.emit('event', { type: 'bus_message_status', messageId, status: 'failed' } as any);
3187
+ }
3188
+ const entry = this.agents.get(agentId);
3189
+ if (entry) entry.state.currentMessageId = undefined;
3190
+ console.error(`[terminal-monitor] ${agentId}: session died, marked message failed`);
3191
+ }
3192
+ }, CHECK_INTERVAL);
3193
+ timer.unref();
3194
+ this.terminalMonitors.set(agentId, timer);
3195
+ }
3196
+
3197
+ /** Stop all terminal monitors (on daemon stop) */
3198
+ private stopAllTerminalMonitors(): void {
3199
+ for (const [, timer] of this.terminalMonitors) clearInterval(timer);
3200
+ this.terminalMonitors.clear();
3201
+ }
3202
+
3203
+ /** Check if all agents are done and no pending work remains */
3204
+ private checkWorkspaceComplete(): void {
3205
+ let allDone = true;
3206
+ for (const [id, entry] of this.agents) {
3207
+ const ws = entry.worker?.getState();
3208
+ const taskSt = ws?.taskStatus ?? entry.state.taskStatus;
3209
+ if (taskSt === 'running' || this.approvalQueue.has(id)) {
3210
+ allDone = false;
3211
+ break;
3212
+ }
3213
+ // idle agents with unmet deps don't block completion
3214
+ if (taskSt === 'idle' && entry.config.dependsOn.length > 0) {
3215
+ const allDepsDone = entry.config.dependsOn.every(depId => {
3216
+ const dep = this.agents.get(depId);
3217
+ return dep && (dep.state.taskStatus === 'done');
3218
+ });
3219
+ if (allDepsDone) {
3220
+ allDone = false; // idle but ready to run = not complete
3221
+ break;
3222
+ }
3223
+ }
3224
+ }
3225
+
3226
+ if (allDone && this.agents.size > 0) {
3227
+ const hasPendingRequests = this.bus.getLog().some(m =>
3228
+ m.type === 'request' && !this.bus.getLog().some(r =>
3229
+ r.type === 'response' && r.payload.replyTo === m.id
3230
+ )
3231
+ );
3232
+ // Also check request documents are all done
3233
+ let requestsComplete = true;
3234
+ try {
3235
+ const { listRequests } = require('./requests');
3236
+ const allReqs = listRequests(this.projectPath);
3237
+ if (allReqs.length > 0) {
3238
+ requestsComplete = allReqs.every((r: any) => r.status === 'done' || r.status === 'rejected');
3239
+ }
3240
+ } catch {}
3241
+
3242
+ if (!hasPendingRequests && requestsComplete) {
3243
+ console.log('[workspace] All agents complete, no pending requests, all request docs done. Workspace done.');
3244
+ this.emit('event', { type: 'workspace_complete' } satisfies OrchestratorEvent);
3245
+ }
3246
+ }
3247
+ }
3248
+
3249
+ /** Get agents that are idle and have all dependencies met */
3250
+ private getReadyAgents(): string[] {
3251
+ const ready: string[] = [];
3252
+ for (const [id, entry] of this.agents) {
3253
+ if (entry.state.taskStatus !== 'idle') continue;
3254
+ const allDepsDone = entry.config.dependsOn.every(depId => {
3255
+ const dep = this.agents.get(depId);
3256
+ return dep && dep.state.taskStatus === 'done';
3257
+ });
3258
+ if (allDepsDone) ready.push(id);
3259
+ }
3260
+ return ready;
3261
+ }
3262
+
3263
+ /**
3264
+ * Parse CLI agent output for bus message markers.
3265
+ * Format: [SEND:TargetLabel:action] content
3266
+ * Example: [SEND:Engineer:fix_request] SQL injection found in auth module
3267
+ */
3268
+ /**
3269
+ * After an agent completes, notify downstream agents that already ran (done/failed)
3270
+ * to re-validate their work. Sets them to waiting_approval so user decides.
3271
+ */
3272
+ private notifyDownstreamForRevalidation(completedAgentId: string, files: string[]): void {
3273
+ const completedLabel = this.agents.get(completedAgentId)?.config.label || completedAgentId;
3274
+
3275
+ for (const [id, entry] of this.agents) {
3276
+ if (id === completedAgentId) continue;
3277
+ if (!entry.config.dependsOn.includes(completedAgentId)) continue;
3278
+
3279
+ // Only notify agents that already completed — they need to re-validate
3280
+ if (entry.state.taskStatus !== 'done' && entry.state.taskStatus !== 'failed') continue;
3281
+
3282
+ console.log(`[workspace] ${completedLabel} changed → ${entry.config.label} needs re-validation`);
3283
+
3284
+ // Send bus message
3285
+ this.bus.send(completedAgentId, id, 'notify', {
3286
+ action: 'update_notify',
3287
+ content: `${completedLabel} completed with changes. Please re-validate.`,
3288
+ files,
3289
+ });
3290
+
3291
+ // Set to waiting_approval so user confirms re-run
3292
+ entry.state.taskStatus = 'idle';
3293
+ entry.state.history.push({
3294
+ type: 'system',
3295
+ subtype: 'revalidation_request',
3296
+ content: `[${completedLabel}] completed with changes — approve to re-run validation`,
3297
+ timestamp: new Date().toISOString(),
3298
+ });
3299
+ this.approvalQueue.add(id);
3300
+ this.emit('event', { type: 'task_status', agentId: id, taskStatus: 'idle' } satisfies WorkerEvent);
3301
+ this.emit('event', {
3302
+ type: 'approval_required',
3303
+ agentId: id,
3304
+ upstreamId: completedAgentId,
3305
+ } satisfies OrchestratorEvent);
3306
+ }
3307
+ }
3308
+
3309
+ /** Track how many history entries have been scanned per agent to avoid re-parsing */
3310
+ private busMarkerScanned = new Map<string, number>();
3311
+
3312
+ private parseBusMarkers(fromAgentId: string, history: { type: string; content: string }[]): void {
3313
+ const markerRegex = /\[SEND:([^:]+):([^\]]+)\]\s*(.+)/g;
3314
+ const labelToId = new Map<string, string>();
3315
+ for (const [id, e] of this.agents) {
3316
+ labelToId.set(e.config.label.toLowerCase(), id);
3317
+ }
3318
+
3319
+ // Only scan new entries since last parse (avoid re-sending from old history)
3320
+ const lastScanned = this.busMarkerScanned.get(fromAgentId) || 0;
3321
+ const newEntries = history.slice(lastScanned);
3322
+ this.busMarkerScanned.set(fromAgentId, history.length);
3323
+
3324
+ for (const entry of newEntries) {
3325
+ let match;
3326
+ while ((match = markerRegex.exec(entry.content)) !== null) {
3327
+ const targetLabel = match[1].trim();
3328
+ const action = match[2].trim();
3329
+ const content = match[3].trim();
3330
+ const targetId = labelToId.get(targetLabel.toLowerCase());
3331
+
3332
+ if (targetId && targetId !== fromAgentId) {
3333
+ console.log(`[bus] Parsed marker from ${fromAgentId}: → ${targetLabel} (${action}): ${content.slice(0, 60)}`);
3334
+ this.bus.send(fromAgentId, targetId, 'notify', { action, content });
3335
+ }
3336
+ }
3337
+ }
3338
+ }
3339
+
3340
+ private saveNow(): void {
3341
+ saveWorkspace(this.getFullState()).catch(() => {});
3342
+ }
3343
+
3344
+ /** Emit agents_changed so SSE pushes the updated list to frontend */
3345
+ private emitAgentsChanged(): void {
3346
+ // Refresh topology cache so MCP queries always return current state
3347
+ this.rebuildTopo();
3348
+ const agents = Array.from(this.agents.values()).map(e => e.config);
3349
+ const agentStates = this.getAllAgentStates();
3350
+ this.emit('event', { type: 'agents_changed', agents, agentStates } satisfies WorkerEvent);
3351
+ }
3352
+
3353
+ private emitWorkspaceStatus(): void {
3354
+ let running = 0, done = 0;
3355
+ for (const [, entry] of this.agents) {
3356
+ const ws = entry.worker?.getState();
3357
+ const taskSt = ws?.taskStatus ?? entry.state.taskStatus;
3358
+ if (taskSt === 'running') running++;
3359
+ if (taskSt === 'done') done++;
3360
+ }
3361
+ this.emit('event', {
3362
+ type: 'workspace_status',
3363
+ running,
3364
+ done,
3365
+ total: this.agents.size,
3366
+ } satisfies OrchestratorEvent);
3367
+ }
3368
+
3369
+ /**
3370
+ * Update agent memory after execution completes.
3371
+ * Parses step results into structured memory entries.
3372
+ */
3373
+ private async updateAgentMemory(agentId: string, config: WorkspaceAgentConfig, stepResults: string[]): Promise<void> {
3374
+ try {
3375
+ const entry = this.agents.get(agentId);
3376
+
3377
+ // Capture observation from the last step (previous steps captured in 'step' event handler)
3378
+ const lastStep = config.steps[config.steps.length - 1];
3379
+ const lastResult = stepResults[stepResults.length - 1];
3380
+ if (lastStep && lastResult) {
3381
+ const obs = parseStepToObservations(lastStep.label, lastResult, entry?.state.artifacts || []);
3382
+ for (const o of obs) {
3383
+ await addObservation(this.workspaceId, agentId, config.label, config.role, o);
3384
+ }
3385
+ }
3386
+
3387
+ // Add session summary
3388
+ const summary = buildSessionSummary(
3389
+ config.steps.map(s => s.label),
3390
+ stepResults,
3391
+ entry?.state.artifacts || [],
3392
+ );
3393
+ await addSessionSummary(this.workspaceId, agentId, summary);
3394
+
3395
+ console.log(`[workspace] Updated memory for ${config.label}`);
3396
+ } catch (err: any) {
3397
+ console.error(`[workspace] Failed to update memory for ${config.label}:`, err.message);
3398
+ }
3399
+ }
3400
+ }