crewly 1.6.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/config/roles/orchestrator/prompt.md +16 -0
  2. package/config/skills/agent/core/get-my-active-work/SKILL.md +101 -0
  3. package/config/skills/agent/core/get-my-active-work/execute.sh +122 -0
  4. package/config/skills/agent/core/record-learning/SKILL.md +29 -0
  5. package/config/skills/agent/core/reply-channel/SKILL.md +41 -0
  6. package/config/skills/agent/core/reply-channel/execute.sh +165 -0
  7. package/config/skills/agent/core/reply-channel/execute.test.sh +148 -0
  8. package/config/skills/agent/remote-browser/execute.sh +296 -14
  9. package/config/skills/agent/remote-browser/execute.test.sh +482 -0
  10. package/config/skills/orchestrator/send-message/SKILL.md +30 -7
  11. package/config/skills/orchestrator/team-health-scan/SKILL.md +98 -0
  12. package/config/skills/orchestrator/team-health-scan/execute.sh +44 -0
  13. package/config/skills/registry.json +62 -1
  14. package/config/slack-app-manifest.json +2 -1
  15. package/config/sops/developer/git-workflow.md +38 -3
  16. package/dist/backend/backend/src/constants.d.ts +69 -1
  17. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  18. package/dist/backend/backend/src/constants.js +69 -2
  19. package/dist/backend/backend/src/constants.js.map +1 -1
  20. package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts +53 -0
  21. package/dist/backend/backend/src/controllers/active-work/active-work.controller.d.ts.map +1 -0
  22. package/dist/backend/backend/src/controllers/active-work/active-work.controller.js +92 -0
  23. package/dist/backend/backend/src/controllers/active-work/active-work.controller.js.map +1 -0
  24. package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.d.ts.map +1 -1
  25. package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js +18 -1
  26. package/dist/backend/backend/src/controllers/agent-stream/agent-stream.controller.js.map +1 -1
  27. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +68 -0
  28. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
  29. package/dist/backend/backend/src/controllers/browser/browser.controller.js +233 -5
  30. package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
  31. package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
  32. package/dist/backend/backend/src/controllers/browser/browser.routes.js +10 -1
  33. package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
  34. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  35. package/dist/backend/backend/src/controllers/chat/chat.controller.js +8 -3
  36. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  37. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts +132 -0
  38. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -0
  39. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +401 -0
  40. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -0
  41. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts +29 -0
  42. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.d.ts.map +1 -0
  43. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js +39 -0
  44. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.routes.js.map +1 -0
  45. package/dist/backend/backend/src/controllers/chat-v2/index.d.ts +8 -0
  46. package/dist/backend/backend/src/controllers/chat-v2/index.d.ts.map +1 -0
  47. package/dist/backend/backend/src/controllers/chat-v2/index.js +8 -0
  48. package/dist/backend/backend/src/controllers/chat-v2/index.js.map +1 -0
  49. package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts +13 -13
  50. package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.d.ts.map +1 -1
  51. package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js +74 -234
  52. package/dist/backend/backend/src/controllers/onboarding/onboarding.routes.js.map +1 -1
  53. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.d.ts.map +1 -1
  54. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js +76 -15
  55. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js.map +1 -1
  56. package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
  57. package/dist/backend/backend/src/controllers/request/request.controller.js +4 -6
  58. package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
  59. package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts +43 -0
  60. package/dist/backend/backend/src/controllers/task-management/tasks.controller.d.ts.map +1 -1
  61. package/dist/backend/backend/src/controllers/task-management/tasks.controller.js +200 -72
  62. package/dist/backend/backend/src/controllers/task-management/tasks.controller.js.map +1 -1
  63. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  64. package/dist/backend/backend/src/controllers/team/team.controller.js +49 -0
  65. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  66. package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts +59 -0
  67. package/dist/backend/backend/src/controllers/team-health/team-health.controller.d.ts.map +1 -0
  68. package/dist/backend/backend/src/controllers/team-health/team-health.controller.js +127 -0
  69. package/dist/backend/backend/src/controllers/team-health/team-health.controller.js.map +1 -0
  70. package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts +13 -0
  71. package/dist/backend/backend/src/controllers/team-health/team-health.routes.d.ts.map +1 -0
  72. package/dist/backend/backend/src/controllers/team-health/team-health.routes.js +20 -0
  73. package/dist/backend/backend/src/controllers/team-health/team-health.routes.js.map +1 -0
  74. package/dist/backend/backend/src/index.d.ts +9 -0
  75. package/dist/backend/backend/src/index.d.ts.map +1 -1
  76. package/dist/backend/backend/src/index.js +233 -0
  77. package/dist/backend/backend/src/index.js.map +1 -1
  78. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  79. package/dist/backend/backend/src/routes/api.routes.js +40 -6
  80. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  81. package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts +498 -0
  82. package/dist/backend/backend/src/services/agent/active-work-briefing.service.d.ts.map +1 -0
  83. package/dist/backend/backend/src/services/agent/active-work-briefing.service.js +759 -0
  84. package/dist/backend/backend/src/services/agent/active-work-briefing.service.js.map +1 -0
  85. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +25 -0
  86. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  87. package/dist/backend/backend/src/services/agent/agent-registration.service.js +221 -58
  88. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  89. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +9 -2
  90. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +35 -2
  92. package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +1 -1
  93. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts +8 -2
  94. package/dist/backend/backend/src/services/agent/crewly-agent/types.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/agent/crewly-agent/types.js +1 -0
  96. package/dist/backend/backend/src/services/agent/crewly-agent/types.js.map +1 -1
  97. package/dist/backend/backend/src/services/agent/tmux-command.service.d.ts.map +1 -1
  98. package/dist/backend/backend/src/services/agent/tmux-command.service.js +2 -1
  99. package/dist/backend/backend/src/services/agent/tmux-command.service.js.map +1 -1
  100. package/dist/backend/backend/src/services/agent/tmux.service.d.ts.map +1 -1
  101. package/dist/backend/backend/src/services/agent/tmux.service.js +2 -1
  102. package/dist/backend/backend/src/services/agent/tmux.service.js.map +1 -1
  103. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +148 -3
  104. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  105. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +241 -2
  106. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  107. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -1
  108. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js +13 -0
  109. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -1
  110. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -1
  111. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js +26 -1
  112. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -1
  113. package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
  114. package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
  115. package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
  116. package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
  117. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +161 -0
  118. package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
  119. package/dist/backend/backend/src/services/browser/browser-bridge.service.js +382 -2
  120. package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
  121. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +105 -0
  122. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
  123. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +232 -13
  124. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  125. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +178 -0
  126. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -0
  127. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +254 -0
  128. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -0
  129. package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts +134 -0
  130. package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.d.ts.map +1 -0
  131. package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js +232 -0
  132. package/dist/backend/backend/src/services/chat-v2/chat-v2.mention-resolver.js.map +1 -0
  133. package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts +25 -0
  134. package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.d.ts.map +1 -0
  135. package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js +23 -0
  136. package/dist/backend/backend/src/services/chat-v2/chat-v2.realtime-holder.js.map +1 -0
  137. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +254 -0
  138. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -0
  139. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +467 -0
  140. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -0
  141. package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts +27 -0
  142. package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.d.ts.map +1 -0
  143. package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js +57 -0
  144. package/dist/backend/backend/src/services/chat-v2/chat-v2.singleton.js.map +1 -0
  145. package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts +43 -0
  146. package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.d.ts.map +1 -0
  147. package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js +54 -0
  148. package/dist/backend/backend/src/services/chat-v2/chat-v2.team-membership.js.map +1 -0
  149. package/dist/backend/backend/src/services/chat-v2/config.d.ts +100 -0
  150. package/dist/backend/backend/src/services/chat-v2/config.d.ts.map +1 -0
  151. package/dist/backend/backend/src/services/chat-v2/config.js +174 -0
  152. package/dist/backend/backend/src/services/chat-v2/config.js.map +1 -0
  153. package/dist/backend/backend/src/services/chat-v2/index.d.ts +11 -0
  154. package/dist/backend/backend/src/services/chat-v2/index.d.ts.map +1 -0
  155. package/dist/backend/backend/src/services/chat-v2/index.js +12 -0
  156. package/dist/backend/backend/src/services/chat-v2/index.js.map +1 -0
  157. package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts +114 -0
  158. package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -0
  159. package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js +194 -0
  160. package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -0
  161. package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts +100 -0
  162. package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.d.ts.map +1 -0
  163. package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js +351 -0
  164. package/dist/backend/backend/src/services/chat-v2/sqlite/chat-db.js.map +1 -0
  165. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +132 -0
  166. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -0
  167. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +281 -0
  168. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -0
  169. package/dist/backend/backend/src/services/chat-v2/types.d.ts +295 -0
  170. package/dist/backend/backend/src/services/chat-v2/types.d.ts.map +1 -0
  171. package/dist/backend/backend/src/services/chat-v2/types.js +61 -0
  172. package/dist/backend/backend/src/services/chat-v2/types.js.map +1 -0
  173. package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts +113 -0
  174. package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.d.ts.map +1 -0
  175. package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js +179 -0
  176. package/dist/backend/backend/src/services/cloud/cloud-event-bridge.service.js.map +1 -0
  177. package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts +131 -0
  178. package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.d.ts.map +1 -0
  179. package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js +227 -0
  180. package/dist/backend/backend/src/services/cloud/cloud-event-forwarder.service.js.map +1 -0
  181. package/dist/backend/backend/src/services/core/config.service.js +3 -3
  182. package/dist/backend/backend/src/services/core/config.service.js.map +1 -1
  183. package/dist/backend/backend/src/services/core/storage.service.d.ts +22 -0
  184. package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
  185. package/dist/backend/backend/src/services/core/storage.service.js +57 -0
  186. package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
  187. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +69 -1
  188. package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
  189. package/dist/backend/backend/src/services/event-bus/event-bus.service.js +118 -0
  190. package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
  191. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +275 -0
  192. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -0
  193. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +736 -0
  194. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -0
  195. package/dist/backend/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
  196. package/dist/backend/backend/src/services/knowledge/fts5-index.service.js +18 -2
  197. package/dist/backend/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
  198. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -13
  199. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
  200. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +123 -29
  201. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
  202. package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts +159 -0
  203. package/dist/backend/backend/src/services/knowledge/learnings-index.service.d.ts.map +1 -0
  204. package/dist/backend/backend/src/services/knowledge/learnings-index.service.js +304 -0
  205. package/dist/backend/backend/src/services/knowledge/learnings-index.service.js.map +1 -0
  206. package/dist/backend/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
  207. package/dist/backend/backend/src/services/knowledge/vector-store.service.js +24 -4
  208. package/dist/backend/backend/src/services/knowledge/vector-store.service.js.map +1 -1
  209. package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts +174 -0
  210. package/dist/backend/backend/src/services/memory/auto-learning.subscriber.d.ts.map +1 -0
  211. package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js +375 -0
  212. package/dist/backend/backend/src/services/memory/auto-learning.subscriber.js.map +1 -0
  213. package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts +97 -0
  214. package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts.map +1 -0
  215. package/dist/backend/backend/src/services/memory/learning-format.validator.js +209 -0
  216. package/dist/backend/backend/src/services/memory/learning-format.validator.js.map +1 -0
  217. package/dist/backend/backend/src/services/memory/vector-store.service.d.ts.map +1 -1
  218. package/dist/backend/backend/src/services/memory/vector-store.service.js +19 -4
  219. package/dist/backend/backend/src/services/memory/vector-store.service.js.map +1 -1
  220. package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts +16 -5
  221. package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.d.ts.map +1 -1
  222. package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js +32 -5
  223. package/dist/backend/backend/src/services/onboarding/onboarding-provision.service.js.map +1 -1
  224. package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts +157 -0
  225. package/dist/backend/backend/src/services/onboarding/onboarding.service.d.ts.map +1 -0
  226. package/dist/backend/backend/src/services/onboarding/onboarding.service.js +229 -0
  227. package/dist/backend/backend/src/services/onboarding/onboarding.service.js.map +1 -0
  228. package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts +141 -0
  229. package/dist/backend/backend/src/services/onboarding/onboarding.types.d.ts.map +1 -0
  230. package/dist/backend/backend/src/services/onboarding/onboarding.types.js +18 -0
  231. package/dist/backend/backend/src/services/onboarding/onboarding.types.js.map +1 -0
  232. package/dist/backend/backend/src/services/pr-review/pr-review.service.d.ts.map +1 -1
  233. package/dist/backend/backend/src/services/pr-review/pr-review.service.js +1 -1
  234. package/dist/backend/backend/src/services/pr-review/pr-review.service.js.map +1 -1
  235. package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -1
  236. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js +17 -1
  237. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js.map +1 -1
  238. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +39 -1
  239. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  240. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +158 -26
  241. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  242. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +248 -6
  243. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  244. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +531 -51
  245. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  246. package/dist/backend/backend/src/services/team-health/index.d.ts +16 -0
  247. package/dist/backend/backend/src/services/team-health/index.d.ts.map +1 -0
  248. package/dist/backend/backend/src/services/team-health/index.js +16 -0
  249. package/dist/backend/backend/src/services/team-health/index.js.map +1 -0
  250. package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts +52 -0
  251. package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts.map +1 -0
  252. package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js +161 -0
  253. package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js.map +1 -0
  254. package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts +53 -0
  255. package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.d.ts.map +1 -0
  256. package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js +88 -0
  257. package/dist/backend/backend/src/services/team-health/lost-dispatch-detector.js.map +1 -0
  258. package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts +44 -0
  259. package/dist/backend/backend/src/services/team-health/stale-trigger-detector.d.ts.map +1 -0
  260. package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js +83 -0
  261. package/dist/backend/backend/src/services/team-health/stale-trigger-detector.js.map +1 -0
  262. package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts +92 -0
  263. package/dist/backend/backend/src/services/team-health/team-health-alert-router.d.ts.map +1 -0
  264. package/dist/backend/backend/src/services/team-health/team-health-alert-router.js +328 -0
  265. package/dist/backend/backend/src/services/team-health/team-health-alert-router.js.map +1 -0
  266. package/dist/backend/backend/src/services/team-health/team-health-config.d.ts +41 -0
  267. package/dist/backend/backend/src/services/team-health/team-health-config.d.ts.map +1 -0
  268. package/dist/backend/backend/src/services/team-health/team-health-config.js +213 -0
  269. package/dist/backend/backend/src/services/team-health/team-health-config.js.map +1 -0
  270. package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts +46 -0
  271. package/dist/backend/backend/src/services/team-health/team-health-detector.d.ts.map +1 -0
  272. package/dist/backend/backend/src/services/team-health/team-health-detector.js +347 -0
  273. package/dist/backend/backend/src/services/team-health/team-health-detector.js.map +1 -0
  274. package/dist/backend/backend/src/services/team-health/team-health-types.d.ts +154 -0
  275. package/dist/backend/backend/src/services/team-health/team-health-types.d.ts.map +1 -0
  276. package/dist/backend/backend/src/services/team-health/team-health-types.js +94 -0
  277. package/dist/backend/backend/src/services/team-health/team-health-types.js.map +1 -0
  278. package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts +111 -0
  279. package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.d.ts.map +1 -0
  280. package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js +226 -0
  281. package/dist/backend/backend/src/services/team-health/team-health-watchdog.service.js.map +1 -0
  282. package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts +148 -0
  283. package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts.map +1 -0
  284. package/dist/backend/backend/src/services/v3/mission-reminder.service.js +545 -0
  285. package/dist/backend/backend/src/services/v3/mission-reminder.service.js.map +1 -0
  286. package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts +499 -0
  287. package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -0
  288. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +1105 -0
  289. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -0
  290. package/dist/backend/backend/src/services/v3/request.service.d.ts +22 -0
  291. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  292. package/dist/backend/backend/src/services/v3/request.service.js +71 -0
  293. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  294. package/dist/backend/backend/src/services/v3/v3-data.service.d.ts +1 -0
  295. package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
  296. package/dist/backend/backend/src/services/v3/v3-data.service.js +22 -6
  297. package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
  298. package/dist/backend/backend/src/types/event-bus.types.d.ts +19 -1
  299. package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
  300. package/dist/backend/backend/src/types/event-bus.types.js +43 -0
  301. package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
  302. package/dist/backend/backend/src/types/index.d.ts +22 -1
  303. package/dist/backend/backend/src/types/index.d.ts.map +1 -1
  304. package/dist/backend/backend/src/types/index.js.map +1 -1
  305. package/dist/backend/backend/src/types/review-reason.types.d.ts +63 -0
  306. package/dist/backend/backend/src/types/review-reason.types.d.ts.map +1 -0
  307. package/dist/backend/backend/src/types/review-reason.types.js +50 -0
  308. package/dist/backend/backend/src/types/review-reason.types.js.map +1 -0
  309. package/dist/backend/backend/src/types/slack.types.d.ts +4 -1
  310. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  311. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  312. package/dist/backend/backend/src/types/v2/mission.types.d.ts +18 -0
  313. package/dist/backend/backend/src/types/v2/mission.types.d.ts.map +1 -1
  314. package/dist/backend/backend/src/types/v2/mission.types.js +1 -0
  315. package/dist/backend/backend/src/types/v2/mission.types.js.map +1 -1
  316. package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  317. package/dist/backend/backend/src/types/v2/work-item.types.js +25 -1
  318. package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
  319. package/dist/backend/backend/src/utils/team.utils.d.ts +38 -0
  320. package/dist/backend/backend/src/utils/team.utils.d.ts.map +1 -0
  321. package/dist/backend/backend/src/utils/team.utils.js +45 -0
  322. package/dist/backend/backend/src/utils/team.utils.js.map +1 -0
  323. package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts +195 -0
  324. package/dist/backend/backend/src/websocket/chat-v2.gateway.d.ts.map +1 -0
  325. package/dist/backend/backend/src/websocket/chat-v2.gateway.js +401 -0
  326. package/dist/backend/backend/src/websocket/chat-v2.gateway.js.map +1 -0
  327. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +37 -2
  328. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
  329. package/dist/backend/backend/src/websocket/terminal.gateway.js +106 -5
  330. package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
  331. package/dist/cli/backend/src/constants.d.ts +69 -1
  332. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  333. package/dist/cli/backend/src/constants.js +69 -2
  334. package/dist/cli/backend/src/constants.js.map +1 -1
  335. package/dist/cli/backend/src/services/core/config.service.js +3 -3
  336. package/dist/cli/backend/src/services/core/config.service.js.map +1 -1
  337. package/dist/cli/backend/src/services/core/storage.service.d.ts +22 -0
  338. package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
  339. package/dist/cli/backend/src/services/core/storage.service.js +57 -0
  340. package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
  341. package/dist/cli/backend/src/services/knowledge/fts5-index.service.d.ts.map +1 -1
  342. package/dist/cli/backend/src/services/knowledge/fts5-index.service.js +18 -2
  343. package/dist/cli/backend/src/services/knowledge/fts5-index.service.js.map +1 -1
  344. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts +49 -13
  345. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
  346. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +123 -29
  347. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
  348. package/dist/cli/backend/src/services/knowledge/vector-store.service.d.ts.map +1 -1
  349. package/dist/cli/backend/src/services/knowledge/vector-store.service.js +24 -4
  350. package/dist/cli/backend/src/services/knowledge/vector-store.service.js.map +1 -1
  351. package/dist/cli/backend/src/types/index.d.ts +22 -1
  352. package/dist/cli/backend/src/types/index.d.ts.map +1 -1
  353. package/dist/cli/backend/src/types/index.js.map +1 -1
  354. package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  355. package/dist/cli/backend/src/types/v2/work-item.types.js +25 -1
  356. package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
  357. package/frontend/dist/assets/{index-70356616.js → index-7a4e7df5.js} +328 -326
  358. package/frontend/dist/assets/index-b7e59b2b.css +33 -0
  359. package/frontend/dist/index.html +2 -2
  360. package/package.json +2 -1
  361. package/config/skills/orchestrator/recall/SKILL.md +0 -47
  362. package/config/skills/orchestrator/recall/execute.sh +0 -13
  363. package/config/skills/orchestrator/record-learning/SKILL.md +0 -47
  364. package/config/skills/orchestrator/record-learning/execute.sh +0 -13
  365. package/config/skills/orchestrator/remember/SKILL.md +0 -55
  366. package/config/skills/orchestrator/remember/execute.sh +0 -15
  367. package/frontend/dist/assets/index-6aaa0630.css +0 -33
@@ -0,0 +1,254 @@
1
+ /**
2
+ * ChatV2DispatcherService — deliver user-origin chat messages to the
3
+ * bound agent session.
4
+ *
5
+ * Flow:
6
+ * HTTP POST /api/chat/channels/:id/messages
7
+ * → ChatV2Service.sendMessage (persist + dedupe)
8
+ * → controller broadcasts WS message frame (user bubble)
9
+ * → controller calls ChatV2Dispatcher.dispatchToAgent(channel, messageDTO)
10
+ * → sendMessageToAgent(agent_session, "[CHAT:<id>] <content>\n<hint>")
11
+ * → agent processes + calls `reply-channel` skill
12
+ * → skill POSTs back to /api/chat/channels/:id/messages as the agent
13
+ * → same controller path → WS message frame (agent bubble)
14
+ *
15
+ * This service is intentionally thin — a couple of dozen lines of glue
16
+ * around the AgentRegistrationService's `sendMessageToAgent` primitive.
17
+ * The dispatch prompt is extracted so tests can assert the format, which
18
+ * is the contract the `reply-channel` skill relies on.
19
+ *
20
+ * @module services/chat-v2/chat-v2.dispatcher.service
21
+ */
22
+ import { LoggerService } from '../core/logger.service.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Prompt formatter
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Default prompt formatter the agent sees when a user sends in their
28
+ * chat channel.
29
+ *
30
+ * Format is intentionally stable and tag-prefixed so the `reply-channel`
31
+ * skill (and future tooling) can reliably extract the channelId without
32
+ * regex ambiguity. The `回复:` hint line gives the agent a one-step
33
+ * instruction on how to reply.
34
+ */
35
+ export function defaultFormatPrompt(args) {
36
+ const { channelId, channelName, senderId, content, clientMessageId } = args;
37
+ const trimmed = content.trim();
38
+ const idHint = clientMessageId ? ` [cmid:${clientMessageId}]` : '';
39
+ return [
40
+ `[CHAT:${channelId}]${idHint} <${senderId}@${channelName}>`,
41
+ ``,
42
+ trimmed,
43
+ ``,
44
+ `---`,
45
+ `回复本频道: 用 \`reply-channel\` skill, 参数 channelId="${channelId}"、content="<your reply>"。`,
46
+ ].join('\n');
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Service
50
+ // ---------------------------------------------------------------------------
51
+ /**
52
+ * Dispatches user-origin chat messages to the agent session bound to the
53
+ * channel. Invoked from the chat controller after `ChatV2Service.sendMessage`
54
+ * returns.
55
+ */
56
+ export class ChatV2DispatcherService {
57
+ agentSink;
58
+ formatPrompt;
59
+ mentionResolver;
60
+ logger;
61
+ constructor(options) {
62
+ this.agentSink = options.agentSink;
63
+ this.formatPrompt = options.formatPrompt ?? defaultFormatPrompt;
64
+ this.mentionResolver = options.mentionResolver;
65
+ this.logger = LoggerService.getInstance().createComponentLogger('ChatV2Dispatcher');
66
+ }
67
+ /**
68
+ * Phase C BE.3 entry point — choose the routing strategy from
69
+ * `channel.type` and the message's mentions, then fan out.
70
+ *
71
+ * Routing rules (SEALED §2.1):
72
+ * - `type='dm'` → existing 1:1 path via `dispatchToAgent`. Mentions
73
+ * in DMs are advisory only (the channel already binds to one
74
+ * agent); the dispatcher does not currently re-route them.
75
+ * - `type='channel'` → resolve `message.mentions` via the injected
76
+ * `mentionResolver`, then dispatch the formatted prompt to each
77
+ * resolved sessionName. No mentions → no dispatch (the message
78
+ * still persists; nobody is paged).
79
+ * - Agent-origin messages always skip dispatch (no self-loopback).
80
+ *
81
+ * Always resolves; per-recipient errors are captured in
82
+ * {@link DispatchMessageResult.mentionOutcomes} and never thrown.
83
+ *
84
+ * @param channel - The channel DTO (provides `type`, name, agentSession).
85
+ * @param message - The persisted message DTO (provides senderType, mentions).
86
+ * @returns Aggregate result describing the strategy + outcomes.
87
+ */
88
+ async dispatchMessage(channel, message) {
89
+ if (message.senderType !== 'user') {
90
+ return {
91
+ strategy: 'skip',
92
+ dispatched: false,
93
+ reason: 'not a user-origin message',
94
+ };
95
+ }
96
+ if (channel.type === 'channel') {
97
+ return this.dispatchChannelMentions(channel, message);
98
+ }
99
+ // Default to the DM path for any other type (including legacy /
100
+ // missing — `type` is non-null after Phase A migration but defensive
101
+ // here keeps the dispatcher robust).
102
+ const dmResult = await this.dispatchToAgent(channel, message);
103
+ return {
104
+ strategy: 'dm',
105
+ dispatched: dmResult.dispatched,
106
+ dmResult,
107
+ };
108
+ }
109
+ /**
110
+ * Dispatch a `type='channel'` message to its resolved mentions.
111
+ *
112
+ * Skips entirely when:
113
+ * - No mention resolver is wired (return strategy=skip).
114
+ * - `mentions` is empty (return strategy=skip).
115
+ * - The resolver returns no targets (return strategy=channel-mentions
116
+ * with empty `mentionOutcomes`; `dispatched=false`).
117
+ *
118
+ * @param channel - The team channel.
119
+ * @param message - The persisted user message.
120
+ * @returns Aggregate result with one outcome per resolved recipient.
121
+ */
122
+ async dispatchChannelMentions(channel, message) {
123
+ if (!this.mentionResolver) {
124
+ this.logger.debug('chat-v2 dispatch skipped — no mention resolver wired', {
125
+ channelId: channel.id,
126
+ messageId: message.id,
127
+ });
128
+ return {
129
+ strategy: 'skip',
130
+ dispatched: false,
131
+ reason: 'no mention resolver wired for type=channel',
132
+ };
133
+ }
134
+ const mentions = Array.isArray(message.mentions) ? message.mentions : [];
135
+ if (mentions.length === 0) {
136
+ return {
137
+ strategy: 'skip',
138
+ dispatched: false,
139
+ reason: 'no mentions on type=channel message',
140
+ };
141
+ }
142
+ const ctx = { teamId: channel.teamId };
143
+ const targets = await this.mentionResolver.resolve(mentions, ctx);
144
+ const outcomes = [];
145
+ let anyDispatched = false;
146
+ for (const target of targets) {
147
+ const prompt = this.formatPrompt({
148
+ channelId: channel.id,
149
+ channelName: channel.name,
150
+ agentSession: target.sessionName,
151
+ senderId: message.senderId,
152
+ content: message.content,
153
+ clientMessageId: typeof message.metadata?.clientMessageId === 'string'
154
+ ? message.metadata.clientMessageId
155
+ : undefined,
156
+ });
157
+ try {
158
+ const result = await this.agentSink.sendMessageToAgent(target.sessionName, prompt);
159
+ if (result.success) {
160
+ outcomes.push({ target, dispatched: true });
161
+ anyDispatched = true;
162
+ }
163
+ else {
164
+ this.logger.warn('chat-v2 mention dispatch reported failure', {
165
+ channelId: channel.id,
166
+ sessionName: target.sessionName,
167
+ err: result.error,
168
+ });
169
+ outcomes.push({
170
+ target,
171
+ dispatched: false,
172
+ error: result.error ?? 'unknown sink failure',
173
+ });
174
+ }
175
+ }
176
+ catch (err) {
177
+ const errMsg = err instanceof Error ? err.message : String(err);
178
+ this.logger.error('chat-v2 mention dispatch threw', {
179
+ channelId: channel.id,
180
+ sessionName: target.sessionName,
181
+ err: errMsg,
182
+ });
183
+ outcomes.push({ target, dispatched: false, error: errMsg });
184
+ }
185
+ }
186
+ return {
187
+ strategy: 'channel-mentions',
188
+ dispatched: anyDispatched,
189
+ mentionOutcomes: outcomes,
190
+ };
191
+ }
192
+ /**
193
+ * Push a newly-persisted user message to the agent.
194
+ *
195
+ * Dispatch is fire-and-forget at the API-response level (the HTTP 201 has
196
+ * already been serialized), but we still await the write so tests can
197
+ * observe the outcome and the logger can record failures.
198
+ *
199
+ * Messages where `senderType !== "user"` are a no-op — we never loop an
200
+ * agent's own reply back into its own PTY.
201
+ *
202
+ * @param channel - Channel DTO (provides `agentSession` + display name)
203
+ * @param message - Persisted message DTO
204
+ */
205
+ async dispatchToAgent(channel, message) {
206
+ if (message.senderType !== 'user') {
207
+ return { dispatched: false, error: 'not a user-origin message' };
208
+ }
209
+ if (!channel.agentSession) {
210
+ this.logger.warn('chat-v2 dispatch skipped — no agentSession', {
211
+ channelId: channel.id,
212
+ });
213
+ return { dispatched: false, error: 'channel has no bound agent' };
214
+ }
215
+ const prompt = this.formatPrompt({
216
+ channelId: channel.id,
217
+ channelName: channel.name,
218
+ agentSession: channel.agentSession,
219
+ senderId: message.senderId,
220
+ content: message.content,
221
+ clientMessageId: typeof message.metadata?.clientMessageId === 'string'
222
+ ? message.metadata.clientMessageId
223
+ : undefined,
224
+ });
225
+ let result;
226
+ try {
227
+ result = await this.agentSink.sendMessageToAgent(channel.agentSession, prompt);
228
+ }
229
+ catch (err) {
230
+ const errMsg = err instanceof Error ? err.message : String(err);
231
+ this.logger.error('chat-v2 dispatch threw', {
232
+ channelId: channel.id,
233
+ agentSession: channel.agentSession,
234
+ err: errMsg,
235
+ });
236
+ return { dispatched: false, error: errMsg };
237
+ }
238
+ if (!result.success) {
239
+ this.logger.warn('chat-v2 dispatch reported failure', {
240
+ channelId: channel.id,
241
+ agentSession: channel.agentSession,
242
+ err: result.error,
243
+ });
244
+ return { dispatched: false, error: result.error ?? 'unknown sink failure' };
245
+ }
246
+ this.logger.debug('chat-v2 dispatched', {
247
+ channelId: channel.id,
248
+ agentSession: channel.agentSession,
249
+ queued: result.queued ?? false,
250
+ });
251
+ return { dispatched: true };
252
+ }
253
+ }
254
+ //# sourceMappingURL=chat-v2.dispatcher.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-v2.dispatcher.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.dispatcher.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * ChatV2MentionResolver — turn `mentions[]` from a chat message into a
3
+ * deduplicated list of agent-session dispatch targets.
4
+ *
5
+ * Phase C BE.2 scaffolding for Slack-like team-chat mention dispatch
6
+ * (SEALED §2.1 routing rules):
7
+ *
8
+ * - **`@agent` mention** (mention id matches a `TeamMember.id`):
9
+ * resolves to that member's tmux/agent `sessionName`. The dispatcher
10
+ * will deliver the message directly into that agent's session.
11
+ *
12
+ * - **`@team` mention** (mention id matches a `Team.id`): resolves to
13
+ * that team's TL — the canonical primary responder per the spec
14
+ * ("the Team Lead is the primary responder; if busy, queue in the
15
+ * Team's Task Pool"). TL is selected as: first member with both
16
+ * `hierarchyLevel === 1` and `canDelegate === true`, falling back
17
+ * to any `canDelegate` member, then `members[0]` so the rule is
18
+ * deterministic even on legacy teams without hierarchy fields.
19
+ *
20
+ * - **Unknown mention id** (not a team or a known member): skipped
21
+ * with a debug log. The dispatcher must always succeed even when
22
+ * the FE includes a stale/typo mention; the chat HTTP ack has
23
+ * already been sent by the time we resolve.
24
+ *
25
+ * Phase C F2a (issue #333) — cross-tenant scope enforcement: when the
26
+ * caller passes `context.teamId`, the resolver enforces the channel's
27
+ * tenant boundary. `@agent` mentions to members of any other team are
28
+ * dropped (cross-tenant leak vector pinned by Arch on PR #331); `@team`
29
+ * mentions to any team still resolve (cross-team pings are a useful
30
+ * coordination affordance), but a mismatch emits a warn for audit.
31
+ *
32
+ * The resolver is the boundary between the chat-v2 wire (id strings)
33
+ * and the agent runtime (session names). It deliberately does NOT
34
+ * touch the agent registry — it only produces the addresses that the
35
+ * dispatcher will hand to `AgentMessageSink.sendMessageToAgent`.
36
+ *
37
+ * The team list is loaded via an injected `loadTeams()` callback so
38
+ * tests can drive it without a real `StorageService`. Production wiring
39
+ * passes `() => storageService.getTeams()`.
40
+ *
41
+ * @module services/chat-v2/chat-v2.mention-resolver
42
+ */
43
+ import type { Team } from '../../types/index.js';
44
+ /** Kind of mention that resolved to a target. */
45
+ export type MentionTargetKind = 'agent' | 'team';
46
+ /**
47
+ * One resolved dispatch target. The dispatcher will call
48
+ * `sendMessageToAgent(sessionName, prompt)` for each unique entry.
49
+ */
50
+ export interface MentionTarget {
51
+ /** Whether this target came from an `@agent` (member) or `@team` mention. */
52
+ kind: MentionTargetKind;
53
+ /** The original mention id as it appeared in the wire `mentions[]`. */
54
+ mentionId: string;
55
+ /** Resolved member id. For `kind='team'`, this is the TL's member id. */
56
+ memberId: string;
57
+ /** Resolved agent session name — the address `sendMessageToAgent` expects. */
58
+ sessionName: string;
59
+ /** For `kind='team'`, the matched team's id. Undefined for `kind='agent'`. */
60
+ teamId?: string;
61
+ }
62
+ /** Optional context the resolver may use to disambiguate. */
63
+ export interface MentionResolverContext {
64
+ /**
65
+ * The channel's `teamId` (when the channel is `type='channel'`). When set,
66
+ * the resolver enforces cross-tenant scope (Phase C F2a, issue #333):
67
+ *
68
+ * - `@agent` mentions are restricted to members whose owning team's
69
+ * id equals `teamId`. Mentions to agents of any other team are
70
+ * dropped with a debug log so a foreign-team agent never receives
71
+ * a dispatch frame from a channel they are not a member of.
72
+ *
73
+ * - `@team` mentions to any team id still resolve to that team's TL
74
+ * (they remain useful for cross-team coordination), but a mismatch
75
+ * between the channel's `teamId` and the mentioned team's id emits
76
+ * a warn so the cross-team ping is observable in audit/log.
77
+ *
78
+ * Leave undefined (or empty string) to disable scoping — used by the
79
+ * legacy DM dispatch path and by tests that need the global resolver.
80
+ */
81
+ teamId?: string;
82
+ }
83
+ /**
84
+ * Dependencies. The team-list source is callable so tests don't need a
85
+ * StorageService; the production path injects `() => storage.getTeams()`.
86
+ */
87
+ export interface MentionResolverDeps {
88
+ /**
89
+ * Returns the current team list. May be sync or async — the resolver
90
+ * awaits the result either way. Errors propagate; the resolver
91
+ * surfaces an empty-target list on caller error so a transient
92
+ * storage hiccup never crashes the chat dispatch path.
93
+ */
94
+ loadTeams: () => Promise<Team[]> | Team[];
95
+ }
96
+ /**
97
+ * Stateless resolver — instances are cheap to construct. Each `resolve()`
98
+ * call loads the team list fresh so dispatch always sees the latest
99
+ * member/session bindings (a new agent comes online → next mention
100
+ * resolves correctly without a restart).
101
+ */
102
+ export declare class ChatV2MentionResolver {
103
+ private readonly loadTeams;
104
+ private readonly logger;
105
+ constructor(deps: MentionResolverDeps);
106
+ /**
107
+ * Resolve `mentions` to dispatch targets.
108
+ *
109
+ * Behavior:
110
+ * - Empty / whitespace mention ids are skipped silently.
111
+ * - Each id is classified as team-first, then agent-first; ties go to
112
+ * the team interpretation since team ids and member ids share the
113
+ * same UUID-shape namespace and team mentions are higher-impact.
114
+ * - Unknown ids are logged at debug level and skipped.
115
+ * - Duplicate `sessionName`s are collapsed (first-seen wins, keeping
116
+ * `kind` ordering stable for tests).
117
+ * - Targets with empty `sessionName` are skipped — there is no agent
118
+ * to dispatch to.
119
+ *
120
+ * Phase C F2a (#333) — when `context.teamId` is set:
121
+ * - `@agent` mentions whose owning team !== `context.teamId` are
122
+ * dropped at debug level (cross-tenant leak guard).
123
+ * - `@team` mentions to a different team still resolve to that
124
+ * team's TL but emit a warn so cross-team pings are auditable.
125
+ * - A blank/whitespace `context.teamId` is treated as "no scope"
126
+ * so DM dispatch and back-compat tests keep current behavior.
127
+ *
128
+ * @param mentions - The raw mention id list from `ChatMessageDTO.mentions`.
129
+ * @param context - Optional resolver context (teamId etc.).
130
+ * @returns Deduplicated dispatch targets, in input order with team-first ties.
131
+ */
132
+ resolve(mentions: string[], context?: MentionResolverContext): Promise<MentionTarget[]>;
133
+ }
134
+ //# sourceMappingURL=chat-v2.mention-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-v2.mention-resolver.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.mention-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,sBAAsB,CAAC;AAQ7D,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,iBAAiB,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,6DAA6D;AAC7D,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC;CAC3C;AAMD;;;;;GAKG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,IAAI,EAAE,mBAAmB;IAKrC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAgJ9F"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * ChatV2MentionResolver — turn `mentions[]` from a chat message into a
3
+ * deduplicated list of agent-session dispatch targets.
4
+ *
5
+ * Phase C BE.2 scaffolding for Slack-like team-chat mention dispatch
6
+ * (SEALED §2.1 routing rules):
7
+ *
8
+ * - **`@agent` mention** (mention id matches a `TeamMember.id`):
9
+ * resolves to that member's tmux/agent `sessionName`. The dispatcher
10
+ * will deliver the message directly into that agent's session.
11
+ *
12
+ * - **`@team` mention** (mention id matches a `Team.id`): resolves to
13
+ * that team's TL — the canonical primary responder per the spec
14
+ * ("the Team Lead is the primary responder; if busy, queue in the
15
+ * Team's Task Pool"). TL is selected as: first member with both
16
+ * `hierarchyLevel === 1` and `canDelegate === true`, falling back
17
+ * to any `canDelegate` member, then `members[0]` so the rule is
18
+ * deterministic even on legacy teams without hierarchy fields.
19
+ *
20
+ * - **Unknown mention id** (not a team or a known member): skipped
21
+ * with a debug log. The dispatcher must always succeed even when
22
+ * the FE includes a stale/typo mention; the chat HTTP ack has
23
+ * already been sent by the time we resolve.
24
+ *
25
+ * Phase C F2a (issue #333) — cross-tenant scope enforcement: when the
26
+ * caller passes `context.teamId`, the resolver enforces the channel's
27
+ * tenant boundary. `@agent` mentions to members of any other team are
28
+ * dropped (cross-tenant leak vector pinned by Arch on PR #331); `@team`
29
+ * mentions to any team still resolve (cross-team pings are a useful
30
+ * coordination affordance), but a mismatch emits a warn for audit.
31
+ *
32
+ * The resolver is the boundary between the chat-v2 wire (id strings)
33
+ * and the agent runtime (session names). It deliberately does NOT
34
+ * touch the agent registry — it only produces the addresses that the
35
+ * dispatcher will hand to `AgentMessageSink.sendMessageToAgent`.
36
+ *
37
+ * The team list is loaded via an injected `loadTeams()` callback so
38
+ * tests can drive it without a real `StorageService`. Production wiring
39
+ * passes `() => storageService.getTeams()`.
40
+ *
41
+ * @module services/chat-v2/chat-v2.mention-resolver
42
+ */
43
+ import { LoggerService } from '../core/logger.service.js';
44
+ import { pickTeamLead } from '../../utils/team.utils.js';
45
+ // ---------------------------------------------------------------------------
46
+ // Service
47
+ // ---------------------------------------------------------------------------
48
+ /**
49
+ * Stateless resolver — instances are cheap to construct. Each `resolve()`
50
+ * call loads the team list fresh so dispatch always sees the latest
51
+ * member/session bindings (a new agent comes online → next mention
52
+ * resolves correctly without a restart).
53
+ */
54
+ export class ChatV2MentionResolver {
55
+ loadTeams;
56
+ logger;
57
+ constructor(deps) {
58
+ this.loadTeams = deps.loadTeams;
59
+ this.logger = LoggerService.getInstance().createComponentLogger('ChatV2MentionResolver');
60
+ }
61
+ /**
62
+ * Resolve `mentions` to dispatch targets.
63
+ *
64
+ * Behavior:
65
+ * - Empty / whitespace mention ids are skipped silently.
66
+ * - Each id is classified as team-first, then agent-first; ties go to
67
+ * the team interpretation since team ids and member ids share the
68
+ * same UUID-shape namespace and team mentions are higher-impact.
69
+ * - Unknown ids are logged at debug level and skipped.
70
+ * - Duplicate `sessionName`s are collapsed (first-seen wins, keeping
71
+ * `kind` ordering stable for tests).
72
+ * - Targets with empty `sessionName` are skipped — there is no agent
73
+ * to dispatch to.
74
+ *
75
+ * Phase C F2a (#333) — when `context.teamId` is set:
76
+ * - `@agent` mentions whose owning team !== `context.teamId` are
77
+ * dropped at debug level (cross-tenant leak guard).
78
+ * - `@team` mentions to a different team still resolve to that
79
+ * team's TL but emit a warn so cross-team pings are auditable.
80
+ * - A blank/whitespace `context.teamId` is treated as "no scope"
81
+ * so DM dispatch and back-compat tests keep current behavior.
82
+ *
83
+ * @param mentions - The raw mention id list from `ChatMessageDTO.mentions`.
84
+ * @param context - Optional resolver context (teamId etc.).
85
+ * @returns Deduplicated dispatch targets, in input order with team-first ties.
86
+ */
87
+ async resolve(mentions, context) {
88
+ if (!Array.isArray(mentions) || mentions.length === 0) {
89
+ return [];
90
+ }
91
+ let teams;
92
+ try {
93
+ teams = await this.loadTeams();
94
+ }
95
+ catch (err) {
96
+ this.logger.warn('chat-v2 mention-resolver loadTeams failed; returning no targets', {
97
+ err: err instanceof Error ? err.message : String(err),
98
+ });
99
+ return [];
100
+ }
101
+ // Build O(1) lookup maps once per call so even a wide mention array
102
+ // (capped at 50 by the service-layer validator) doesn't cause an
103
+ // O(N*M) team×member scan.
104
+ const teamById = new Map();
105
+ const memberById = new Map();
106
+ for (const team of teams) {
107
+ teamById.set(team.id, team);
108
+ for (const member of team.members ?? []) {
109
+ // First-seen wins on member-id collisions across teams. The
110
+ // legacy data model allows distinct teams to coexist with the
111
+ // same memberId only if both were imported from the same
112
+ // hierarchy backup — which is rare and never a chat path. We
113
+ // log the collision so it surfaces in observability.
114
+ if (memberById.has(member.id)) {
115
+ this.logger.warn('chat-v2 mention-resolver member-id collision across teams', {
116
+ memberId: member.id,
117
+ firstTeamId: memberById.get(member.id).team.id,
118
+ secondTeamId: team.id,
119
+ });
120
+ continue;
121
+ }
122
+ memberById.set(member.id, { team, member });
123
+ }
124
+ }
125
+ const results = [];
126
+ const seenSessions = new Set();
127
+ // Treat blank/whitespace teamId as "no scope" so callers don't have to
128
+ // pre-normalize. This matches the channel-rail listing endpoint's
129
+ // teamId filter normalization (see ChatV2Service.listChannels).
130
+ const scopeTeamId = typeof context?.teamId === 'string' && context.teamId.trim().length > 0
131
+ ? context.teamId
132
+ : undefined;
133
+ for (const rawId of mentions) {
134
+ if (typeof rawId !== 'string')
135
+ continue;
136
+ const id = rawId.trim();
137
+ if (id.length === 0)
138
+ continue;
139
+ // 1) Team-mention takes precedence (higher routing impact).
140
+ const team = teamById.get(id);
141
+ if (team) {
142
+ // F2a (#333): when the channel scopes to a team, a `@team` mention
143
+ // to ANY OTHER team still resolves (deliberate — cross-team pings
144
+ // are a useful coordination affordance), but we emit a warn so
145
+ // operators can audit cross-tenant traffic. No warn on same-team
146
+ // mentions; that's the common case.
147
+ if (scopeTeamId !== undefined && team.id !== scopeTeamId) {
148
+ this.logger.warn('chat-v2 mention-resolver cross-team @team mention', {
149
+ mentionId: id,
150
+ mentionedTeamId: team.id,
151
+ contextTeamId: scopeTeamId,
152
+ });
153
+ }
154
+ const tl = pickTeamLead(team);
155
+ if (!tl) {
156
+ this.logger.debug('chat-v2 mention-resolver team has no dispatchable TL', {
157
+ mentionId: id,
158
+ teamId: team.id,
159
+ });
160
+ continue;
161
+ }
162
+ if (!tl.sessionName) {
163
+ this.logger.debug('chat-v2 mention-resolver TL has empty sessionName', {
164
+ mentionId: id,
165
+ teamId: team.id,
166
+ memberId: tl.id,
167
+ });
168
+ continue;
169
+ }
170
+ if (seenSessions.has(tl.sessionName))
171
+ continue;
172
+ seenSessions.add(tl.sessionName);
173
+ results.push({
174
+ kind: 'team',
175
+ mentionId: id,
176
+ memberId: tl.id,
177
+ sessionName: tl.sessionName,
178
+ teamId: team.id,
179
+ });
180
+ continue;
181
+ }
182
+ // 2) Agent (member) mention.
183
+ const hit = memberById.get(id);
184
+ if (hit) {
185
+ // F2a (#333): when the channel scopes to a team, drop @agent
186
+ // mentions whose owning team differs — without this, a
187
+ // type='channel' message in team-A could fan-out to an agent in
188
+ // team-B, the cross-tenant leak vector pinned by Arch on PR #331.
189
+ // The mention silently no-ops at debug level (the chat HTTP ack
190
+ // already returned 200; we don't fail the post for a dropped
191
+ // mention).
192
+ if (scopeTeamId !== undefined && hit.team.id !== scopeTeamId) {
193
+ this.logger.debug('chat-v2 mention-resolver dropping foreign-team @agent', {
194
+ mentionId: id,
195
+ mentionedMemberId: hit.member.id,
196
+ mentionedTeamId: hit.team.id,
197
+ contextTeamId: scopeTeamId,
198
+ });
199
+ continue;
200
+ }
201
+ if (!hit.member.sessionName) {
202
+ this.logger.debug('chat-v2 mention-resolver member has empty sessionName', {
203
+ mentionId: id,
204
+ memberId: hit.member.id,
205
+ teamId: hit.team.id,
206
+ });
207
+ continue;
208
+ }
209
+ if (seenSessions.has(hit.member.sessionName))
210
+ continue;
211
+ seenSessions.add(hit.member.sessionName);
212
+ results.push({
213
+ kind: 'agent',
214
+ mentionId: id,
215
+ memberId: hit.member.id,
216
+ sessionName: hit.member.sessionName,
217
+ });
218
+ continue;
219
+ }
220
+ this.logger.debug('chat-v2 mention-resolver unknown mention id', {
221
+ mentionId: id,
222
+ contextTeamId: scopeTeamId,
223
+ });
224
+ }
225
+ return results;
226
+ }
227
+ }
228
+ // ---------------------------------------------------------------------------
229
+ // Helpers — `pickTeamLead` lives in `utils/team.utils.ts` so chat-v2 and
230
+ // mission-reminder share the canonical 4-rule cascade. Imported above.
231
+ // ---------------------------------------------------------------------------
232
+ //# sourceMappingURL=chat-v2.mention-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-v2.mention-resolver.js","sourceRoot":"","sources":["../../../../../../backend/src/services/chat-v2/chat-v2.mention-resolver.ts"],"names":[],"mappings":"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"}