@mndrk/agx 2.4.2 → 2.4.4

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 (347) hide show
  1. package/cloud-runtime/standalone/apps/local/.next/BUILD_ID +1 -1
  2. package/cloud-runtime/standalone/apps/local/.next/app-path-routes-manifest.json +5 -0
  3. package/cloud-runtime/standalone/apps/local/.next/build-manifest.json +2 -2
  4. package/cloud-runtime/standalone/apps/local/.next/prerender-manifest.json +3 -3
  5. package/cloud-runtime/standalone/apps/local/.next/routes-manifest.json +41 -0
  6. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.html +2 -2
  7. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.rsc +1 -1
  8. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/cloud-runtime/standalone/apps/local/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.html +2 -2
  15. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.rsc +2 -2
  16. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  17. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/cloud-runtime/standalone/apps/local/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/cloud-runtime/standalone/apps/local/.next/server/app/agents/[id]/page.js.nft.json +1 -1
  23. package/cloud-runtime/standalone/apps/local/.next/server/app/agents/[id]/page_client-reference-manifest.js +1 -1
  24. package/cloud-runtime/standalone/apps/local/.next/server/app/agents/page.js.nft.json +1 -1
  25. package/cloud-runtime/standalone/apps/local/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  26. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.html +2 -2
  27. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.rsc +3 -3
  28. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_full.segment.rsc +3 -3
  29. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_head.segment.rsc +1 -1
  30. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_index.segment.rsc +2 -2
  31. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/_tree.segment.rsc +2 -2
  32. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/agents/__PAGE__.segment.rsc +2 -2
  33. package/cloud-runtime/standalone/apps/local/.next/server/app/agents.segments/agents.segment.rsc +1 -1
  34. package/cloud-runtime/standalone/apps/local/.next/server/app/api/agent-specs/route.js.nft.json +1 -1
  35. package/cloud-runtime/standalone/apps/local/.next/server/app/api/agents/[id]/profile/route.js.nft.json +1 -1
  36. package/cloud-runtime/standalone/apps/local/.next/server/app/api/agents/export/route.js.nft.json +1 -1
  37. package/cloud-runtime/standalone/apps/local/.next/server/app/api/chat/route.js.nft.json +1 -1
  38. package/cloud-runtime/standalone/apps/local/.next/server/app/api/file-search/route.js.nft.json +1 -1
  39. package/cloud-runtime/standalone/apps/local/.next/server/app/api/participants/route.js.nft.json +1 -1
  40. package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/objectives/[objectiveId]/scheduled-tasks/route.js.nft.json +1 -1
  41. package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/objectives/[objectiveId]/worker/route.js.nft.json +1 -1
  42. package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/search/route.js.nft.json +1 -1
  43. package/cloud-runtime/standalone/apps/local/.next/server/app/api/projects/[id]/teams/route.js.nft.json +1 -1
  44. package/cloud-runtime/standalone/apps/local/.next/server/app/api/prompt-jobs/poll/route.js.nft.json +1 -1
  45. package/cloud-runtime/standalone/apps/local/.next/server/app/api/providers/check/[id]/route.js.nft.json +1 -1
  46. package/cloud-runtime/standalone/apps/local/.next/server/app/api/providers/route.js.nft.json +1 -1
  47. package/cloud-runtime/standalone/apps/local/.next/server/app/api/queue/route.js.nft.json +1 -1
  48. package/cloud-runtime/standalone/apps/local/.next/server/app/api/schedules/debug/route.js.nft.json +1 -1
  49. package/cloud-runtime/standalone/apps/local/.next/server/app/api/schedules/poll/route.js.nft.json +1 -1
  50. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/assign/route.js.nft.json +1 -1
  51. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/available/route.js.nft.json +1 -1
  52. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/detail/route.js.nft.json +1 -1
  53. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/history/route.js.nft.json +1 -1
  54. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/learn/route.js.nft.json +1 -1
  55. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/route.js.nft.json +1 -1
  56. package/cloud-runtime/standalone/apps/local/.next/server/app/api/skills/unlearn/route.js.nft.json +1 -1
  57. package/cloud-runtime/standalone/apps/local/.next/server/app/api/status/route.js.nft.json +1 -1
  58. package/cloud-runtime/standalone/apps/local/.next/server/app/api/summarize/route.js.nft.json +1 -1
  59. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/comments/[commentId]/route.js.nft.json +1 -1
  60. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/comments/route.js.nft.json +1 -1
  61. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/nodes/[nodeId]/comments/route.js +1 -1
  62. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/nodes/[nodeId]/comments/route.js.nft.json +1 -1
  63. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/nodes/[nodeId]/verify/route.js.nft.json +1 -1
  64. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
  65. package/cloud-runtime/standalone/apps/local/.next/server/app/api/tasks/route.js.nft.json +1 -1
  66. package/cloud-runtime/standalone/apps/local/.next/server/app/api/threads/knowledge/route.js.nft.json +1 -1
  67. package/cloud-runtime/standalone/apps/local/.next/server/app/api/threads/route.js.nft.json +1 -1
  68. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/auth/route.js +3 -3
  69. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/auth/route.js.nft.json +1 -1
  70. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/callback/route.js +3 -3
  71. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/callback/route.js.nft.json +1 -1
  72. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/groups/route.js +3 -3
  73. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/groups/route.js.nft.json +1 -1
  74. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/activity/route.js +3 -3
  75. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/activity/route.js.nft.json +1 -1
  76. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/recap/route.js +3 -3
  77. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/recap/route.js.nft.json +1 -1
  78. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/route.js +4 -4
  79. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/[id]/route.js.nft.json +1 -1
  80. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/route.js +3 -3
  81. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/items/route.js.nft.json +1 -1
  82. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/app-paths-manifest.json +3 -0
  83. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/build-manifest.json +11 -0
  84. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route/server-reference-manifest.json +4 -0
  85. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js +7 -0
  86. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js.map +5 -0
  87. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route.js.nft.json +1 -0
  88. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/[id]/route_client-reference-manifest.js +2 -0
  89. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/app-paths-manifest.json +3 -0
  90. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/build-manifest.json +11 -0
  91. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route/server-reference-manifest.json +4 -0
  92. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js +7 -0
  93. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js.map +5 -0
  94. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route.js.nft.json +1 -0
  95. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/labels/route_client-reference-manifest.js +2 -0
  96. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/mcp-setup/route.js +3 -3
  97. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/mcp-setup/route.js.nft.json +1 -1
  98. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/app-paths-manifest.json +3 -0
  99. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/build-manifest.json +11 -0
  100. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route/server-reference-manifest.json +4 -0
  101. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js +7 -0
  102. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js.map +5 -0
  103. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route.js.nft.json +1 -0
  104. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/bulk/route_client-reference-manifest.js +2 -0
  105. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/app-paths-manifest.json +3 -0
  106. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/build-manifest.json +11 -0
  107. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route/server-reference-manifest.json +4 -0
  108. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js +7 -0
  109. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js.map +5 -0
  110. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route.js.nft.json +1 -0
  111. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/metadata/route_client-reference-manifest.js +2 -0
  112. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/options/route.js +3 -3
  113. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/options/route.js.nft.json +1 -1
  114. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/[id]/route.js +1 -1
  115. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/[id]/route.js.nft.json +1 -1
  116. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/route.js +3 -3
  117. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/route.js.nft.json +1 -1
  118. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/scripted/route.js +1 -1
  119. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/runs/scripted/route.js.nft.json +1 -1
  120. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/app-paths-manifest.json +3 -0
  121. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/build-manifest.json +11 -0
  122. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route/server-reference-manifest.json +4 -0
  123. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js +7 -0
  124. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js.map +5 -0
  125. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route.js.nft.json +1 -0
  126. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/stats/route_client-reference-manifest.js +2 -0
  127. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/status/route.js +4 -4
  128. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/status/route.js.nft.json +1 -1
  129. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token/route.js +3 -3
  130. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token/route.js.nft.json +1 -1
  131. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token-receive/route.js +3 -3
  132. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/token-receive/route.js.nft.json +1 -1
  133. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/worker/route.js +6 -6
  134. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/[tracker]/worker/route.js.nft.json +1 -1
  135. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/connections/route.js +7 -2
  136. package/cloud-runtime/standalone/apps/local/.next/server/app/api/trackers/connections/route.js.nft.json +1 -1
  137. package/cloud-runtime/standalone/apps/local/.next/server/app/api/update-check/route.js.nft.json +1 -1
  138. package/cloud-runtime/standalone/apps/local/.next/server/app/index.html +2 -2
  139. package/cloud-runtime/standalone/apps/local/.next/server/app/index.rsc +2 -2
  140. package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  141. package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_full.segment.rsc +2 -2
  142. package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_head.segment.rsc +1 -1
  143. package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_index.segment.rsc +2 -2
  144. package/cloud-runtime/standalone/apps/local/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  145. package/cloud-runtime/standalone/apps/local/.next/server/app/page_client-reference-manifest.js +1 -1
  146. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page/react-loadable-manifest.json +2 -2
  147. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page.js.nft.json +1 -1
  148. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/automations/page_client-reference-manifest.js +1 -1
  149. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/env-vars/page.js.nft.json +1 -1
  150. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/env-vars/page_client-reference-manifest.js +1 -1
  151. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/folders/page.js.nft.json +1 -1
  152. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/folders/page_client-reference-manifest.js +1 -1
  153. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/graph/[taskId]/page.js.nft.json +1 -1
  154. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/graph/[taskId]/page_client-reference-manifest.js +1 -1
  155. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/[objectiveId]/page.js.nft.json +1 -1
  156. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/[objectiveId]/page_client-reference-manifest.js +1 -1
  157. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/page.js.nft.json +1 -1
  158. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/objectives/page_client-reference-manifest.js +1 -1
  159. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  160. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  161. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/agents/[agentId]/page.js.nft.json +1 -1
  162. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/agents/[agentId]/page_client-reference-manifest.js +1 -1
  163. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/page.js.nft.json +1 -1
  164. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/[teamId]/page_client-reference-manifest.js +1 -1
  165. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/adopt/page.js.nft.json +1 -1
  166. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/adopt/page_client-reference-manifest.js +1 -1
  167. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/new/page.js.nft.json +1 -1
  168. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/new/page_client-reference-manifest.js +1 -1
  169. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/page.js.nft.json +1 -1
  170. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/page_client-reference-manifest.js +1 -1
  171. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/replace/page.js.nft.json +1 -1
  172. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/teams/replace/page_client-reference-manifest.js +1 -1
  173. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/terminal/page.js.nft.json +1 -1
  174. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/terminal/page_client-reference-manifest.js +1 -1
  175. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/thread/[threadId]/page.js.nft.json +1 -1
  176. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/thread/[threadId]/page_client-reference-manifest.js +1 -1
  177. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page/react-loadable-manifest.json +1 -1
  178. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page.js.nft.json +1 -1
  179. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/[tracker]/page_client-reference-manifest.js +1 -1
  180. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/connect/page.js.nft.json +1 -1
  181. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/connect/page_client-reference-manifest.js +1 -1
  182. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page/react-loadable-manifest.json +1 -1
  183. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page.js.nft.json +1 -1
  184. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/[slug]/tracking/page_client-reference-manifest.js +1 -1
  185. package/cloud-runtime/standalone/apps/local/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  186. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.html +2 -2
  187. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.rsc +2 -2
  188. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  189. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  190. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  191. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  192. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/projects/__PAGE__.segment.rsc +1 -1
  193. package/cloud-runtime/standalone/apps/local/.next/server/app/projects.segments/projects.segment.rsc +1 -1
  194. package/cloud-runtime/standalone/apps/local/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  195. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.html +2 -2
  196. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.rsc +2 -2
  197. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_full.segment.rsc +2 -2
  198. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_head.segment.rsc +1 -1
  199. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_index.segment.rsc +2 -2
  200. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  201. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +1 -1
  202. package/cloud-runtime/standalone/apps/local/.next/server/app/setup.segments/setup.segment.rsc +1 -1
  203. package/cloud-runtime/standalone/apps/local/.next/server/app/status/page_client-reference-manifest.js +1 -1
  204. package/cloud-runtime/standalone/apps/local/.next/server/app/status.html +2 -2
  205. package/cloud-runtime/standalone/apps/local/.next/server/app/status.rsc +2 -2
  206. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_full.segment.rsc +2 -2
  207. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_head.segment.rsc +1 -1
  208. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_index.segment.rsc +2 -2
  209. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/_tree.segment.rsc +2 -2
  210. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/status/__PAGE__.segment.rsc +1 -1
  211. package/cloud-runtime/standalone/apps/local/.next/server/app/status.segments/status.segment.rsc +1 -1
  212. package/cloud-runtime/standalone/apps/local/.next/server/app-paths-manifest.json +5 -0
  213. package/cloud-runtime/standalone/apps/local/.next/server/chunks/083c9_next-internal_server_app_api_trackers_[tracker]_metadata_route_actions_c83fcc1a.js +3 -0
  214. package/cloud-runtime/standalone/apps/local/.next/server/chunks/30bdd_server_app_api_trackers_[tracker]_labels_[id]_route_actions_2646388d.js +3 -0
  215. package/cloud-runtime/standalone/apps/local/.next/server/chunks/30bdd_server_app_api_trackers_[tracker]_metadata_bulk_route_actions_f43e6831.js +3 -0
  216. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__0e04eca4._.js +40 -0
  217. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__0fbbaf2d._.js +1 -1
  218. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__10a90219._.js +3 -3
  219. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__1d970ad0._.js +40 -0
  220. package/cloud-runtime/standalone/apps/local/.next/server/chunks/{[root-of-the-server]__2ab23e45._.js → [root-of-the-server]__2eb13697._.js} +2 -2
  221. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__3a038592._.js +3 -3
  222. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__3b27260f._.js +23 -8
  223. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__498d8b2d._.js +3 -0
  224. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__580ddcca._.js +40 -0
  225. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__5da8d281._.js +129 -0
  226. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__68b692c4._.js +9 -9
  227. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__76030d44._.js +40 -0
  228. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__7db7c421._.js +20 -5
  229. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__7fcbb0c2._.js +2 -2
  230. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__ba72d342._.js +5 -5
  231. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__d8cc43c7._.js +22 -7
  232. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__f598d976._.js +1 -1
  233. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__f7a936d9._.js +21 -6
  234. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_1a4cb196._.js +1 -1
  235. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_5e5f36c4._.js +1 -1
  236. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_8f9f647d._.js +28 -13
  237. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_9f0fd451._.js +3 -0
  238. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_d256aa32._.js +28 -25
  239. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_e1f4d9ad._.js +1 -1
  240. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_f8b3abae._.js +1 -1
  241. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_lib_orchestrator_chat-processor_ts_46384f36._.js +12 -12
  242. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_lib_tracker_tracker-run-store_ts_5aa9592e._.js +22 -7
  243. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ebff2__next-internal_server_app_api_trackers_[tracker]_labels_route_actions_8ba41152.js +3 -0
  244. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ebff2__next-internal_server_app_api_trackers_[tracker]_stats_route_actions_7da4ccde.js +3 -0
  245. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{[root-of-the-server]__799f4d13._.js → [root-of-the-server]__2af44092._.js} +2 -2
  246. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__452cb0f0._.js +3 -0
  247. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__489568b4._.js +3 -0
  248. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__4ec098a0._.js +3 -0
  249. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__53bd50df._.js +3 -0
  250. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__7774a40c._.js +3 -0
  251. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__b8484b0e._.js +7 -0
  252. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{[root-of-the-server]__51edc9b6._.js → [root-of-the-server]__bd05ee09._.js} +2 -2
  253. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/_8c4beba9._.js +7 -0
  254. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_5eebb5cb._.js +1 -1
  255. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/{apps_local_35d90b5d._.js → apps_local_bbb7b83b._.js} +2 -2
  256. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_components_TrackerBoard_tsx_98970bab._.js +6 -6
  257. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_components_chat-ui_f0554cb4._.js +1 -1
  258. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/apps_local_components_projects_ProjectObjectivesWorkspace_tsx_751ab3d3._.js +7 -7
  259. package/cloud-runtime/standalone/apps/local/.next/server/functions-config-manifest.json +5 -0
  260. package/cloud-runtime/standalone/apps/local/.next/server/middleware-manifest.json +5 -5
  261. package/cloud-runtime/standalone/apps/local/.next/server/pages/404.html +2 -2
  262. package/cloud-runtime/standalone/apps/local/.next/server/pages/500.html +2 -2
  263. package/cloud-runtime/standalone/apps/local/.next/server/server-reference-manifest.js +1 -1
  264. package/cloud-runtime/standalone/apps/local/.next/server/server-reference-manifest.json +1 -1
  265. package/cloud-runtime/standalone/apps/local/.next/static/chunks/0243e7d015db440d.js +5 -0
  266. package/cloud-runtime/standalone/apps/local/.next/static/chunks/42a62b80b32a97f7.js +9 -0
  267. package/cloud-runtime/standalone/apps/local/.next/static/chunks/5d047fc7267a8f53.js +16 -0
  268. package/cloud-runtime/standalone/apps/local/.next/static/chunks/7148feb61274d431.css +1 -0
  269. package/cloud-runtime/standalone/apps/local/.next/static/chunks/716e1716d526ded9.js +46 -0
  270. package/cloud-runtime/standalone/apps/local/.next/static/chunks/{77cea126364aab3c.js → 7353a3a1fcd5825c.js} +1 -1
  271. package/cloud-runtime/standalone/apps/local/.next/static/chunks/8b91e7692a899f00.js +20 -0
  272. package/cloud-runtime/standalone/apps/local/.next/static/chunks/9acdd370e9daca0d.js +16 -0
  273. package/cloud-runtime/standalone/apps/local/.next/static/chunks/{6c777fe66e042eec.js → 9df45611d6c84e02.js} +1 -1
  274. package/cloud-runtime/standalone/apps/local/.next/static/chunks/{6c278ae4535b6d5c.js → 9e2208153f276f8c.js} +1 -1
  275. package/cloud-runtime/standalone/apps/local/.next/static/chunks/a084c6475513e6fe.js +16 -0
  276. package/cloud-runtime/standalone/apps/local/.next/static/chunks/aa6db7c91c1ccd5f.js +16 -0
  277. package/cloud-runtime/standalone/apps/local/.next/static/chunks/d5607ac80145f3b7.js +1 -0
  278. package/cloud-runtime/standalone/apps/local/.next/static/chunks/d590384ce3045a12.js +5 -0
  279. package/cloud-runtime/standalone/apps/local/.next/static/chunks/{d5b14e14665024a9.js → d5c307b52fd87861.js} +1 -1
  280. package/cloud-runtime/standalone/apps/local/.next/static/chunks/f4acf76cb6c82c73.js +16 -0
  281. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/labels/[id]/route.ts +23 -0
  282. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/labels/route.ts +41 -0
  283. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/metadata/bulk/route.ts +68 -0
  284. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/metadata/route.ts +31 -0
  285. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/options/route.ts +1 -0
  286. package/cloud-runtime/standalone/apps/local/app/api/trackers/[tracker]/stats/route.ts +20 -0
  287. package/cloud-runtime/standalone/apps/local/app/api/trackers/connections/route.ts +46 -2
  288. package/cloud-runtime/standalone/apps/local/app/projects/[slug]/tracking/connect/page.tsx +41 -11
  289. package/cloud-runtime/standalone/apps/local/components/TrackerBoard.tsx +609 -85
  290. package/cloud-runtime/standalone/apps/local/components/projects/ProjectObjectivesWorkspace.tsx +204 -49
  291. package/cloud-runtime/standalone/apps/local/components/tracker/FibonacciPicker.tsx +41 -0
  292. package/cloud-runtime/standalone/apps/local/components/tracker/FolderRow.tsx +1 -1
  293. package/cloud-runtime/standalone/apps/local/components/tracker/LabelPicker.tsx +118 -0
  294. package/cloud-runtime/standalone/apps/local/components/tracker/LabelSettings.tsx +104 -0
  295. package/cloud-runtime/standalone/apps/local/components/tracker/PromptPopover.tsx +64 -0
  296. package/cloud-runtime/standalone/apps/local/components/tracker/SelectionBar.tsx +276 -23
  297. package/cloud-runtime/standalone/apps/local/components/tracker/StatusGroupRow.tsx +50 -0
  298. package/cloud-runtime/standalone/apps/local/components/tracker/TicketPanel.tsx +14 -2
  299. package/cloud-runtime/standalone/apps/local/components/tracker/TicketRow.tsx +147 -7
  300. package/cloud-runtime/standalone/apps/local/components/tracker/TrackerSettingsModal.tsx +14 -2
  301. package/cloud-runtime/standalone/apps/local/components/ui/ResizeHandle.tsx +15 -22
  302. package/cloud-runtime/standalone/apps/local/hooks/useTrackerConnections.ts +29 -1
  303. package/cloud-runtime/standalone/apps/local/hooks/useTrackerIssueStats.ts +52 -0
  304. package/cloud-runtime/standalone/apps/local/hooks/useTrackerItemMetadata.ts +67 -0
  305. package/cloud-runtime/standalone/apps/local/hooks/useTrackerItemsMetadata.ts +51 -0
  306. package/cloud-runtime/standalone/apps/local/hooks/useTrackerLabels.ts +74 -0
  307. package/cloud-runtime/standalone/apps/local/hooks/useTrackerRuns.ts +5 -0
  308. package/cloud-runtime/standalone/apps/local/lib/agent-process-registry.ts +8 -2
  309. package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/jira/adapter.tsx +1 -0
  310. package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/jira/issues.ts +1 -0
  311. package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/adapter.tsx +1 -0
  312. package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/client.ts +5 -0
  313. package/cloud-runtime/standalone/apps/local/lib/tracker/adapters/linear/issues.ts +1 -0
  314. package/cloud-runtime/standalone/apps/local/lib/tracker/connections.ts +46 -15
  315. package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-adapter.ts +2 -0
  316. package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-item-metadata-store.ts +262 -0
  317. package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-item-store.ts +10 -3
  318. package/cloud-runtime/standalone/apps/local/lib/tracker/tracker-run-store.ts +42 -0
  319. package/cloud-runtime/standalone/apps/local/src/prompt-scheduler/objective-worker.ts +7 -0
  320. package/cloud-runtime/standalone/apps/local/src/prompt-scheduler/task-worker.ts +7 -0
  321. package/cloud-runtime/standalone/apps/local/state/trackerBoardFilters.ts +4 -0
  322. package/cloud-runtime/standalone/apps/local/worker/index.js +6 -2
  323. package/package.json +1 -1
  324. package/cloud-runtime/standalone/apps/local/.next/server/chunks/[root-of-the-server]__847236fb._.js +0 -3
  325. package/cloud-runtime/standalone/apps/local/.next/server/chunks/apps_local_80b34b78._.js +0 -3
  326. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__30bf097e._.js +0 -3
  327. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__46ae9d33._.js +0 -3
  328. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__50fd8680._.js +0 -3
  329. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__8059a285._.js +0 -3
  330. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__886953ec._.js +0 -7
  331. package/cloud-runtime/standalone/apps/local/.next/server/chunks/ssr/[root-of-the-server]__97160565._.js +0 -3
  332. package/cloud-runtime/standalone/apps/local/.next/static/chunks/0876dfd6ce07abaf.js +0 -9
  333. package/cloud-runtime/standalone/apps/local/.next/static/chunks/1ec83777a9abd420.js +0 -16
  334. package/cloud-runtime/standalone/apps/local/.next/static/chunks/286758b0fd546c68.js +0 -16
  335. package/cloud-runtime/standalone/apps/local/.next/static/chunks/a72ed5cb3feb0d51.js +0 -5
  336. package/cloud-runtime/standalone/apps/local/.next/static/chunks/b02c180ad1d968eb.js +0 -16
  337. package/cloud-runtime/standalone/apps/local/.next/static/chunks/b048a4812b51f97a.js +0 -1
  338. package/cloud-runtime/standalone/apps/local/.next/static/chunks/c63d97c917d96f47.js +0 -46
  339. package/cloud-runtime/standalone/apps/local/.next/static/chunks/d3bf70e2fbdc0ae5.js +0 -5
  340. package/cloud-runtime/standalone/apps/local/.next/static/chunks/dd5a56eea2d4c067.js +0 -16
  341. package/cloud-runtime/standalone/apps/local/.next/static/chunks/dd7d7c382389b8b9.js +0 -16
  342. package/cloud-runtime/standalone/apps/local/.next/static/chunks/e72724fd8225ec39.js +0 -20
  343. package/cloud-runtime/standalone/apps/local/.next/static/chunks/ec92e3bd6c2db6e6.css +0 -1
  344. package/cloud-runtime/standalone/apps/local/.next/static/chunks/ffcc32453866d0c2.js +0 -1
  345. /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 3-6VaSnGGXdV-2eV44RDK}/_buildManifest.js +0 -0
  346. /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 3-6VaSnGGXdV-2eV44RDK}/_clientMiddlewareManifest.json +0 -0
  347. /package/cloud-runtime/standalone/apps/local/.next/static/{QEldoF1LdgJqO0PgpmUmx → 3-6VaSnGGXdV-2eV44RDK}/_ssgManifest.js +0 -0
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
- import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import React, { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
4
4
  import dynamic from "next/dynamic";
5
- import { ArrowDown, ArrowUp, ChevronLeft, Clock, FileText, Play, Plus, RefreshCw, Search, Settings, User, X } from "lucide-react";
5
+ import { ArrowDown, ArrowUp, ChevronDown, ChevronLeft, ChevronRight, Clock, FileText, Play, Plus, RefreshCw, Search, Settings, User, X } from "lucide-react";
6
6
  import { useUrlSelection } from "@/hooks/useUrlSelection";
7
7
  import { useTrackerItems } from "@/hooks/useTrackerItems";
8
8
  import type { TrackerItem, TrackerStatusCategory } from "@/lib/tracker/types";
@@ -56,12 +56,16 @@ import { TicketRow } from "@/components/tracker/TicketRow";
56
56
  import { TicketPanel } from "@/components/tracker/TicketPanel";
57
57
  import { useTrackerParticipants } from "@/hooks/useTrackerParticipants";
58
58
  import { useTrackerActiveAgents } from "@/hooks/useTrackerActiveAgents";
59
+ import { useTrackerIssueStats } from "@/hooks/useTrackerIssueStats";
59
60
  import { agentAvatarUrl } from "@/lib/tracker-board-utils";
60
61
  import { useTaskGroups, type TaskGroup } from "@/hooks/useTaskGroups";
61
62
  import { FolderRow } from "@/components/tracker/FolderRow";
62
63
  import { GroupPanel } from "@/components/tracker/GroupPanel";
63
64
  import { GroupNamePrompt, PENDING_GROUP_DROP_ID } from "@/components/tracker/GroupNamePrompt";
65
+ import { StatusGroupRow, STATUS_GROUP_PREFIX } from "@/components/tracker/StatusGroupRow";
64
66
  import { SelectionBar } from "@/components/tracker/SelectionBar";
67
+ import { useTrackerItemsMetadata } from "@/hooks/useTrackerItemsMetadata";
68
+ import { useTrackerLabels } from "@/hooks/useTrackerLabels";
65
69
  import {
66
70
  DndContext,
67
71
  DragOverlay,
@@ -89,6 +93,13 @@ function formatRunTime(iso: string): string {
89
93
  });
90
94
  }
91
95
 
96
+ const STATUS_CATEGORY_COLORS: Record<string, string> = {
97
+ todo: "bg-zinc-400",
98
+ in_progress: "bg-amber-400",
99
+ done: "bg-emerald-400",
100
+ cancelled: "bg-red-400",
101
+ };
102
+
92
103
  interface GroupOption {
93
104
  id: string;
94
105
  name: string;
@@ -405,16 +416,20 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
405
416
  const [selectedAssigneeIds, setSelectedAssigneeIds] = useState<string[]>([]);
406
417
  const [selectedStatusCategories, setSelectedStatusCategories] = useState<string[]>([]);
407
418
  const [groups, setGroups] = useState<GroupOption[]>([]);
419
+ const [groupLabel, setGroupLabel] = useState("Group");
408
420
  const [selectedGroupId, setSelectedGroupId] = useState("");
409
421
  const [selectedWorkspaceId, setSelectedWorkspaceId] = useState("");
410
422
  const [sortBy, setSortBy] = useState<"activity" | "identifier" | "status" | "created">("activity");
411
423
  const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
412
- const [hasActivity, setHasActivity] = useState(false);
424
+ const [selectedLabelNames, setSelectedLabelNames] = useState<string[]>([]);
413
425
  const [pinnedItemIds, setPinnedItemIds] = useState<Set<string>>(() => loadPinnedTrackerItemIds(trackerType, projectSlug));
414
426
  const [selectedItemFallback, setSelectedItemFallback] = useState<TrackerItem | null>(null);
415
427
  const [updatingItemId, setUpdatingItemId] = useState<string | null>(null);
428
+ const [collapsedStatusGroups, setCollapsedStatusGroups] = useState<Set<string>>(new Set());
429
+ const groupByStatus = true;
416
430
  const { participants } = useTrackerParticipants(trackerType, projectId);
417
431
  const { issueActiveAgents } = useTrackerActiveAgents(trackerType, projectId);
432
+ const { issueStats } = useTrackerIssueStats(trackerType, projectId);
418
433
  const [pickerItem, setPickerItem] = useState<TrackerItem | null>(null);
419
434
  const [pickerAnchor, setPickerAnchor] = useState<{ top: number; left: number } | null>(null);
420
435
  const [touchPanelTab, setTouchPanelTab] = useState<"runs" | "ticket">("runs");
@@ -480,6 +495,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
480
495
  // hoisting issues (sortedItems is declared further down).
481
496
  const sortedItemsRef = useRef<TrackerItem[]>([]);
482
497
 
498
+ // Ref to handleItemStatusChange so handleDragEnd can access it without
499
+ // hoisting issues (handleItemStatusChange is declared further down).
500
+ const handleItemStatusChangeRef = useRef<((item: TrackerItem, status: string, statusCategory?: TrackerStatusCategory) => Promise<void>) | null>(null);
501
+
483
502
  const handleMultiSelectGroup = useCallback(() => {
484
503
  const ids = Array.from(multiSelectedItemIds);
485
504
  // Find the topmost selected item in the sorted list to position the prompt
@@ -550,6 +569,25 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
550
569
  if (!over || active.id === over.id) return;
551
570
  const overId = over.id as string;
552
571
 
572
+ // Dropped on a status group header → change status upstream
573
+ if (overId.startsWith(STATUS_GROUP_PREFIX)) {
574
+ const targetStatus = overId.slice(STATUS_GROUP_PREFIX.length);
575
+ const activeItem = sortedItemsRef.current.find((i) => i.id === activeItemId);
576
+ const targetCategory = sortedItemsRef.current.find((i) => i.status === targetStatus)?.statusCategory;
577
+ if (activeItem && activeItem.status !== targetStatus) {
578
+ await handleItemStatusChangeRef.current?.(activeItem, targetStatus, targetCategory);
579
+ }
580
+ return;
581
+ }
582
+
583
+ // Dropped on a ticket in a different status group → change status
584
+ const activeItem = sortedItemsRef.current.find((i) => i.id === activeItemId);
585
+ const overItem = sortedItemsRef.current.find((i) => i.id === overId);
586
+ if (activeItem && overItem && activeItem.status !== overItem.status) {
587
+ await handleItemStatusChangeRef.current?.(activeItem, overItem.status, overItem.statusCategory);
588
+ return;
589
+ }
590
+
553
591
  // Check if dropping on a folder
554
592
  const targetGroup = taskGroups.find((g) => g.id === overId);
555
593
  if (targetGroup) {
@@ -616,7 +654,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
616
654
  setSelectedGroupId(storedFilters.groupIds?.[0] ?? "");
617
655
  setSortBy(storedFilters.sortBy);
618
656
  setSortDir(storedFilters.sortDir);
619
- setHasActivity(storedFilters.hasActivity);
657
+ setSelectedLabelNames(storedFilters.labelNames ?? []);
620
658
  setPinnedItemIds(loadPinnedTrackerItemIds(trackerType, projectSlug));
621
659
  }, [trackerType, projectSlug]);
622
660
 
@@ -631,11 +669,12 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
631
669
  assigneeIds: selectedAssigneeIds,
632
670
  statusCategories: selectedStatusCategories,
633
671
  groupIds: selectedGroupId ? [selectedGroupId] : [],
672
+ labelNames: selectedLabelNames,
634
673
  sortBy,
635
674
  sortDir,
636
- hasActivity,
675
+ hasActivity: false,
637
676
  });
638
- }, [trackerType, projectSlug, search, selectedAssigneeIds, selectedStatusCategories, selectedWorkspaceId, selectedGroupId, sortBy, sortDir, hasActivity]);
677
+ }, [trackerType, projectSlug, search, selectedAssigneeIds, selectedStatusCategories, selectedWorkspaceId, selectedGroupId, selectedLabelNames, sortBy, sortDir]);
639
678
 
640
679
  // Fetch filter options when connected
641
680
  useEffect(() => {
@@ -657,7 +696,8 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
657
696
  setAssignees(Array.isArray(data.assignees) ? data.assignees : []);
658
697
  setStatusCategories(Array.isArray(data.statuses) ? data.statuses.map((s: { name: string; category: string }) => ({ value: s.name, label: s.name })) : []);
659
698
  setWorkspaces(Array.isArray(data.teams) ? data.teams : []);
660
- setGroups(Array.isArray(data.cycles) ? data.cycles : []);
699
+ setGroups(Array.isArray(data.groups) ? data.groups : []);
700
+ if (data.groupLabel) setGroupLabel(data.groupLabel);
661
701
  setFilterOptionsLoaded(true);
662
702
  })
663
703
  .catch(() => {
@@ -731,9 +771,8 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
731
771
  groupIds: selectedGroupId ? [selectedGroupId] : undefined,
732
772
  sortBy,
733
773
  sortDir,
734
- hasActivity: hasActivity || undefined,
735
774
  }),
736
- [debouncedSearch, selectedAssigneeIds, selectedGroupId, selectedStatusCategories, statusCategories.length, sortBy, sortDir, hasActivity]
775
+ [debouncedSearch, selectedAssigneeIds, selectedGroupId, selectedStatusCategories, statusCategories.length, sortBy, sortDir]
737
776
  );
738
777
 
739
778
  const {
@@ -746,6 +785,22 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
746
785
  } = useTrackerItems(trackerType, filters, connected && filterOptionsLoaded && Boolean(projectId), {
747
786
  projectId: projectId ?? "",
748
787
  });
788
+
789
+ // Bulk metadata for visible items
790
+ const visibleIssueIds = useMemo(() => items.map((item) => item.id), [items]);
791
+ const {
792
+ metadataMap,
793
+ refresh: refreshMetadata,
794
+ } = useTrackerItemsMetadata(trackerType, projectId, visibleIssueIds);
795
+
796
+ // Labels
797
+ const {
798
+ labels: allLabels,
799
+ definitions: labelDefinitions,
800
+ refresh: refreshLabels,
801
+ createDefinition: createLabelDefinition,
802
+ } = useTrackerLabels(trackerType, projectId);
803
+
749
804
  const selectedItemFromList = useMemo(
750
805
  () => (selectedItemId ? items.find((item) => item.id === selectedItemId) ?? null : null),
751
806
  [items, selectedItemId],
@@ -769,9 +824,45 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
769
824
  }, [items, pinnedItemIds]);
770
825
  sortedItemsRef.current = sortedItems;
771
826
 
827
+ const deferredLabelNames = useDeferredValue(selectedLabelNames);
828
+ const labelFilteredItems = useMemo(() => {
829
+ if (deferredLabelNames.length === 0) return sortedItems;
830
+ const filterSet = new Set(deferredLabelNames);
831
+ const result: TrackerItem[] = [];
832
+ for (const item of sortedItems) {
833
+ const labels = metadataMap.get(item.id)?.labels;
834
+ if (!labels) continue;
835
+ for (const l of labels) {
836
+ if (filterSet.has(l)) {
837
+ result.push(item);
838
+ break;
839
+ }
840
+ }
841
+ }
842
+ return result;
843
+ }, [sortedItems, deferredLabelNames, metadataMap]);
844
+
845
+ const statusGroups = useMemo(() => {
846
+ if (!groupByStatus) return [];
847
+ const map = new Map<string, { status: string; category: TrackerStatusCategory; items: TrackerItem[] }>();
848
+ for (const item of labelFilteredItems) {
849
+ let group = map.get(item.status);
850
+ if (!group) {
851
+ group = { status: item.status, category: item.statusCategory, items: [] };
852
+ map.set(item.status, group);
853
+ }
854
+ group.items.push(item);
855
+ }
856
+ const categoryOrder: Record<string, number> = { in_progress: 0, todo: 1, done: 2, cancelled: 3 };
857
+ return [...map.values()].sort(
858
+ (a, b) => (categoryOrder[a.category] ?? 1) - (categoryOrder[b.category] ?? 1)
859
+ );
860
+ }, [groupByStatus, labelFilteredItems]);
861
+
772
862
  const {
773
863
  runs,
774
864
  loading: runsLoading,
865
+ loadedForIssueId: runsLoadedForIssueId,
775
866
  createRun,
776
867
  updateRun,
777
868
  } = useTrackerRuns(trackerType, selectedItem?.id ?? null, projectId ?? null);
@@ -815,26 +906,64 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
815
906
  );
816
907
  const groupOptions = useMemo<FilterOption[]>(
817
908
  () => [
818
- { value: "", label: "Group" },
909
+ { value: "", label: groupLabel },
819
910
  ...groups.map((group) => ({
820
911
  value: group.id,
821
912
  label: group.name,
822
913
  })),
823
914
  ],
824
- [groups]
915
+ [groups, groupLabel]
825
916
  );
826
917
  const showStatusFilter = statusOptions.length > 0;
827
918
  const showGroupFilter = groupOptions.length > 1;
828
919
  const showWorkspaceFilter = workspaceOptions.length > 2;
829
920
  const activeSessionScriptLabel = activeScript?.name ?? "AGX default";
830
921
 
922
+ const labelFilterOptions = useMemo<FilterOption[]>(
923
+ () => allLabels.map((l) => ({ value: l.name, label: l.name })),
924
+ [allLabels]
925
+ );
926
+
927
+ const handleItemToggleLabel = useCallback(async (itemId: string, label: string) => {
928
+ if (!projectId) return;
929
+ const current = metadataMap.get(itemId)?.labels ?? [];
930
+ const has = current.includes(label);
931
+ const next = has ? current.filter((l) => l !== label) : [...current, label];
932
+ try {
933
+ await fetch(`/api/trackers/${trackerType}/metadata?projectId=${encodeURIComponent(projectId)}&issueId=${encodeURIComponent(itemId)}`, {
934
+ method: "PATCH",
935
+ headers: { "Content-Type": "application/json" },
936
+ body: JSON.stringify({ labels: next }),
937
+ });
938
+ void refreshMetadata();
939
+ void refreshLabels();
940
+ } catch {}
941
+ }, [projectId, trackerType, metadataMap, refreshMetadata, refreshLabels]);
942
+
943
+ const handleItemAddLabel = useCallback(async (name: string) => {
944
+ if (!projectId) return;
945
+ await createLabelDefinition(name);
946
+ }, [projectId, createLabelDefinition]);
947
+
831
948
  const handleItemStatusChange = useCallback(
832
- async (item: TrackerItem, status: string) => {
949
+ async (item: TrackerItem, status: string, statusCategory?: TrackerStatusCategory) => {
833
950
  const nextStatus = status.trim();
834
951
  if (!nextStatus || nextStatus === item.status || !projectId) {
835
952
  return;
836
953
  }
837
954
 
955
+ // Optimistic update — move the ticket to the new status immediately so
956
+ // the UI reflects the drop before the PATCH round-trip completes.
957
+ const optimisticItem: TrackerItem = {
958
+ ...item,
959
+ status: nextStatus,
960
+ statusCategory: statusCategory ?? item.statusCategory,
961
+ };
962
+ updateItem(optimisticItem);
963
+ if (selectedItemId === item.id) {
964
+ setSelectedItemFallback(optimisticItem);
965
+ }
966
+
838
967
  setUpdatingItemId(item.id);
839
968
  try {
840
969
  const response = await fetch(
@@ -861,6 +990,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
861
990
  }
862
991
  await refreshItems();
863
992
  } catch (error) {
993
+ // Revert optimistic update on failure.
994
+ updateItem(item);
995
+ if (selectedItemId === item.id) {
996
+ setSelectedItemFallback(item);
997
+ }
864
998
  if (error instanceof Error) {
865
999
  window.alert(error.message);
866
1000
  }
@@ -871,6 +1005,161 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
871
1005
  [refreshItems, selectedItemId, updateItem, trackerType, projectId]
872
1006
  );
873
1007
 
1008
+ // Update the ref whenever the callback changes
1009
+ handleItemStatusChangeRef.current = handleItemStatusChange;
1010
+
1011
+ const handleBulkRecap = useCallback(async () => {
1012
+ const ids = Array.from(multiSelectedItemIds);
1013
+ const selectedItems = ids
1014
+ .map((id) => items.find((item) => item.id === id))
1015
+ .filter(Boolean) as TrackerItem[];
1016
+
1017
+ if (selectedItems.length === 0 || participants.length === 0) return;
1018
+ const agent = participants[0];
1019
+
1020
+ for (const item of selectedItems) {
1021
+ try {
1022
+ await fetch(`/api/trackers/${trackerType}/runs/scripted`, {
1023
+ method: "POST",
1024
+ headers: { "Content-Type": "application/json" },
1025
+ body: JSON.stringify({
1026
+ projectId: projectId ?? undefined,
1027
+ projectSlug: projectSlug ?? undefined,
1028
+ issueId: item.id,
1029
+ issueIdentifier: item.identifier,
1030
+ issueTitle: item.title,
1031
+ issueStatus: item.status,
1032
+ issueAssignee: item.assignee?.name ?? null,
1033
+ agentId: agent.id,
1034
+ scriptName: "Recap",
1035
+ scriptPrompt: "Summarize recent activity and current state of this ticket. Focus on: what was done, what's outstanding, and any blockers.",
1036
+ }),
1037
+ });
1038
+ } catch (err) {
1039
+ console.error(`Failed to start recap for ${item.identifier}:`, err);
1040
+ }
1041
+ }
1042
+ setMultiSelectedItemIds(new Set());
1043
+ }, [multiSelectedItemIds, items, participants, trackerType, projectId, projectSlug]);
1044
+
1045
+ const handleBulkPrompt = useCallback(async (prompt: string, agentId: string) => {
1046
+ const ids = Array.from(multiSelectedItemIds);
1047
+ const selectedItems = ids
1048
+ .map((id) => items.find((item) => item.id === id))
1049
+ .filter(Boolean) as TrackerItem[];
1050
+
1051
+ for (const item of selectedItems) {
1052
+ try {
1053
+ await fetch(`/api/trackers/${trackerType}/runs/scripted`, {
1054
+ method: "POST",
1055
+ headers: { "Content-Type": "application/json" },
1056
+ body: JSON.stringify({
1057
+ projectId: projectId ?? undefined,
1058
+ projectSlug: projectSlug ?? undefined,
1059
+ issueId: item.id,
1060
+ issueIdentifier: item.identifier,
1061
+ issueTitle: item.title,
1062
+ issueStatus: item.status,
1063
+ issueAssignee: item.assignee?.name ?? null,
1064
+ agentId,
1065
+ scriptPrompt: prompt,
1066
+ }),
1067
+ });
1068
+ } catch (err) {
1069
+ console.error(`Failed to send prompt for ${item.identifier}:`, err);
1070
+ }
1071
+ }
1072
+ setMultiSelectedItemIds(new Set());
1073
+ }, [multiSelectedItemIds, items, trackerType, projectId, projectSlug]);
1074
+
1075
+ const handleBulkEstimate = useCallback(async (estimate: number | null) => {
1076
+ const ids = Array.from(multiSelectedItemIds);
1077
+ if (ids.length === 0 || !projectId) return;
1078
+ try {
1079
+ await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
1080
+ method: "POST",
1081
+ headers: { "Content-Type": "application/json" },
1082
+ body: JSON.stringify({
1083
+ projectId,
1084
+ issueIds: ids,
1085
+ action: "set_estimate",
1086
+ payload: { estimate },
1087
+ }),
1088
+ });
1089
+ void refreshMetadata();
1090
+ } catch {}
1091
+ setMultiSelectedItemIds(new Set());
1092
+ }, [multiSelectedItemIds, projectId, trackerType, refreshMetadata]);
1093
+
1094
+ const handleBulkAddLabel = useCallback(async (label: string) => {
1095
+ const ids = Array.from(multiSelectedItemIds);
1096
+ if (ids.length === 0 || !projectId) return;
1097
+ try {
1098
+ await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
1099
+ method: "POST",
1100
+ headers: { "Content-Type": "application/json" },
1101
+ body: JSON.stringify({
1102
+ projectId,
1103
+ issueIds: ids,
1104
+ action: "add_labels",
1105
+ payload: { labels: [label] },
1106
+ }),
1107
+ });
1108
+ void refreshMetadata();
1109
+ void refreshLabels();
1110
+ } catch {}
1111
+ }, [multiSelectedItemIds, projectId, trackerType, refreshMetadata, refreshLabels]);
1112
+
1113
+ const handleBulkRemoveLabel = useCallback(async (label: string) => {
1114
+ const ids = Array.from(multiSelectedItemIds);
1115
+ if (ids.length === 0 || !projectId) return;
1116
+ try {
1117
+ await fetch(`/api/trackers/${trackerType}/metadata/bulk`, {
1118
+ method: "POST",
1119
+ headers: { "Content-Type": "application/json" },
1120
+ body: JSON.stringify({
1121
+ projectId,
1122
+ issueIds: ids,
1123
+ action: "remove_label",
1124
+ payload: { label },
1125
+ }),
1126
+ });
1127
+ void refreshMetadata();
1128
+ void refreshLabels();
1129
+ } catch {}
1130
+ }, [multiSelectedItemIds, projectId, trackerType, refreshMetadata, refreshLabels]);
1131
+
1132
+ const [bulkStatusUpdating, setBulkStatusUpdating] = useState(false);
1133
+
1134
+ const handleBulkStatus = useCallback(async (status: string) => {
1135
+ const ids = Array.from(multiSelectedItemIds);
1136
+ const selectedItems = ids
1137
+ .map((id) => items.find((item) => item.id === id))
1138
+ .filter(Boolean) as TrackerItem[];
1139
+
1140
+ if (selectedItems.length === 0) return;
1141
+ setBulkStatusUpdating(true);
1142
+ for (const item of selectedItems) {
1143
+ await handleItemStatusChange(item, status);
1144
+ }
1145
+ setBulkStatusUpdating(false);
1146
+ setMultiSelectedItemIds(new Set());
1147
+ }, [multiSelectedItemIds, items, handleItemStatusChange]);
1148
+
1149
+ const handleCreateLabel = useCallback(async (name: string) => {
1150
+ if (!projectId) return;
1151
+ await createLabelDefinition(name);
1152
+ }, [projectId, createLabelDefinition]);
1153
+
1154
+ const selectedMetadata = useMemo(() => {
1155
+ const map = new Map<string, { labels: string[]; estimate: number | null }>();
1156
+ for (const id of multiSelectedItemIds) {
1157
+ const meta = metadataMap.get(id);
1158
+ map.set(id, meta ?? { labels: [], estimate: null });
1159
+ }
1160
+ return map;
1161
+ }, [multiSelectedItemIds, metadataMap]);
1162
+
874
1163
  useEffect(() => {
875
1164
  if (!selectedItemId || !projectId) {
876
1165
  setSelectedItemFallback(null);
@@ -948,12 +1237,12 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
948
1237
  }, [selectedItemId, selectedRunId]);
949
1238
 
950
1239
  useEffect(() => {
951
- if (!isAwaitingRestore || runsLoading || runs.length === 0) return;
1240
+ if (!isAwaitingRestore || runsLoading || runsLoadedForIssueId !== selectedItemId) return;
952
1241
  lastRestoredItemRef.current = selectedItemId;
953
1242
  if (storedRunId && runs.some((r) => r.id === storedRunId)) {
954
1243
  replaceSelection({ run: storedRunId });
955
1244
  }
956
- }, [isAwaitingRestore, storedRunId, selectedItemId, runs, runsLoading, replaceSelection]);
1245
+ }, [isAwaitingRestore, storedRunId, selectedItemId, runs, runsLoading, runsLoadedForIssueId, replaceSelection]);
957
1246
 
958
1247
  useEffect(() => {
959
1248
  if (!isTouchLayout) {
@@ -1156,6 +1445,16 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1156
1445
  onChange={setSelectedAssigneeIds}
1157
1446
  emptyLabel="All assignees"
1158
1447
  />
1448
+ {labelFilterOptions.length > 0 && (
1449
+ <MultiFilterPopdown
1450
+ label="Label"
1451
+ values={selectedLabelNames}
1452
+ options={labelFilterOptions}
1453
+ activeClasses="border-pink-500/30 bg-pink-500/10 text-pink-400"
1454
+ onChange={setSelectedLabelNames}
1455
+ emptyLabel="All labels"
1456
+ />
1457
+ )}
1159
1458
  {showWorkspaceFilter ? (
1160
1459
  <FilterSelect
1161
1460
  label="Workspace"
@@ -1167,7 +1466,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1167
1466
  ) : null}
1168
1467
  {showGroupFilter ? (
1169
1468
  <FilterSelect
1170
- label="Group"
1469
+ label={groupLabel}
1171
1470
  value={selectedGroupId}
1172
1471
  options={groupOptions}
1173
1472
  activeClasses="border-purple-500/30 bg-purple-500/10 text-purple-400"
@@ -1178,10 +1477,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1178
1477
  label="Sort"
1179
1478
  value={sortBy}
1180
1479
  options={[
1181
- { value: "activity", label: "Activity" },
1480
+ { value: "activity", label: "Updated At" },
1182
1481
  { value: "identifier", label: "Ticket ID" },
1183
1482
  { value: "status", label: "Status" },
1184
- { value: "created", label: "Created" },
1483
+ { value: "created", label: "Created At" },
1185
1484
  ]}
1186
1485
  activeClasses="border-sky-500/30 bg-sky-500/10 text-sky-400"
1187
1486
  onChange={(value) => setSortBy(value as typeof sortBy)}
@@ -1194,17 +1493,6 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1194
1493
  >
1195
1494
  {sortDir === "desc" ? <ArrowDown size={12} /> : <ArrowUp size={12} />}
1196
1495
  </button>
1197
- <button
1198
- type="button"
1199
- className={`flex items-center gap-1 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors ${
1200
- hasActivity
1201
- ? "border-orange-500/30 bg-orange-500/10 text-orange-400"
1202
- : "border-[var(--card-border)] text-[var(--muted-foreground)] hover:bg-[var(--card-bg)]"
1203
- }`}
1204
- onClick={() => setHasActivity((v) => !v)}
1205
- >
1206
- My activity
1207
- </button>
1208
1496
  </div>
1209
1497
  </div>
1210
1498
 
@@ -1219,31 +1507,90 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1219
1507
  </div>
1220
1508
  ) : (
1221
1509
  <>
1222
- {sortedItems.map((item, idx) => (
1223
- <React.Fragment key={item.id}>
1224
- {pinnedItemIds.size > 0 &&
1225
- !pinnedItemIds.has(item.id) &&
1226
- (idx === 0 || pinnedItemIds.has(sortedItems[idx - 1].id)) && (
1227
- <div className="mx-4 border-t border-amber-500/20" />
1228
- )}
1229
- <TicketRow
1230
- item={item}
1231
- selected={selectedItem?.id === item.id}
1232
- pinned={pinnedItemIds.has(item.id)}
1233
- activeAgents={issueActiveAgents.get(item.id)}
1234
- participants={participants}
1235
- projectSlug={projectSlug}
1236
- onSelect={() => {
1237
- setTouchPanelTab("runs");
1238
- pushSelection({
1239
- issue: item.id,
1240
- run: null,
1241
- });
1242
- }}
1243
- onTogglePin={() => togglePin(item.id)}
1244
- />
1245
- </React.Fragment>
1246
- ))}
1510
+ {groupByStatus ? (
1511
+ statusGroups.map((sg) => {
1512
+ const collapsed = collapsedStatusGroups.has(sg.status);
1513
+ return (
1514
+ <React.Fragment key={`sg-${sg.status}`}>
1515
+ <StatusGroupRow
1516
+ status={sg.status}
1517
+ categoryColor={STATUS_CATEGORY_COLORS[sg.category] ?? "bg-zinc-400"}
1518
+ count={sg.items.length}
1519
+ collapsed={collapsed}
1520
+ onToggle={() =>
1521
+ setCollapsedStatusGroups((prev) => {
1522
+ const next = new Set(prev);
1523
+ if (next.has(sg.status)) next.delete(sg.status);
1524
+ else next.add(sg.status);
1525
+ return next;
1526
+ })
1527
+ }
1528
+ />
1529
+ {!collapsed &&
1530
+ sg.items.map((item) => (
1531
+ <TicketRow
1532
+ key={item.id}
1533
+ item={item}
1534
+ selected={selectedItem?.id === item.id}
1535
+ pinned={pinnedItemIds.has(item.id)}
1536
+ activeAgents={issueActiveAgents.get(item.id)}
1537
+ participants={participants}
1538
+ projectSlug={projectSlug}
1539
+ stats={issueStats.get(item.id)}
1540
+ hideStatus
1541
+ estimate={metadataMap.get(item.id)?.estimate}
1542
+ localLabels={metadataMap.get(item.id)?.labels}
1543
+ labelDefinitions={labelDefinitions}
1544
+ allLabels={allLabels}
1545
+ onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
1546
+ onAddLabel={handleItemAddLabel}
1547
+ onSelect={() => {
1548
+ setTouchPanelTab("runs");
1549
+ pushSelection({
1550
+ issue: item.id,
1551
+ run: null,
1552
+ });
1553
+ }}
1554
+ onTogglePin={() => togglePin(item.id)}
1555
+ />
1556
+ ))}
1557
+ </React.Fragment>
1558
+ );
1559
+ })
1560
+ ) : (
1561
+ labelFilteredItems.map((item, idx) => (
1562
+ <React.Fragment key={item.id}>
1563
+ {pinnedItemIds.size > 0 &&
1564
+ !pinnedItemIds.has(item.id) &&
1565
+ (idx === 0 || pinnedItemIds.has(labelFilteredItems[idx - 1].id)) && (
1566
+ <div className="mx-4 border-t border-amber-500/20" />
1567
+ )}
1568
+ <TicketRow
1569
+ item={item}
1570
+ selected={selectedItem?.id === item.id}
1571
+ pinned={pinnedItemIds.has(item.id)}
1572
+ activeAgents={issueActiveAgents.get(item.id)}
1573
+ participants={participants}
1574
+ projectSlug={projectSlug}
1575
+ stats={issueStats.get(item.id)}
1576
+ estimate={metadataMap.get(item.id)?.estimate}
1577
+ localLabels={metadataMap.get(item.id)?.labels}
1578
+ labelDefinitions={labelDefinitions}
1579
+ allLabels={allLabels}
1580
+ onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
1581
+ onAddLabel={handleItemAddLabel}
1582
+ onSelect={() => {
1583
+ setTouchPanelTab("runs");
1584
+ pushSelection({
1585
+ issue: item.id,
1586
+ run: null,
1587
+ });
1588
+ }}
1589
+ onTogglePin={() => togglePin(item.id)}
1590
+ />
1591
+ </React.Fragment>
1592
+ ))
1593
+ )}
1247
1594
  {hasMore ? (
1248
1595
  <div
1249
1596
  ref={sentinelRef}
@@ -1488,6 +1835,16 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1488
1835
  onChange={setSelectedAssigneeIds}
1489
1836
  emptyLabel="All assignees"
1490
1837
  />
1838
+ {labelFilterOptions.length > 0 && (
1839
+ <MultiFilterPopdown
1840
+ label="Label"
1841
+ values={selectedLabelNames}
1842
+ options={labelFilterOptions}
1843
+ activeClasses="border-pink-500/30 bg-pink-500/10 text-pink-400"
1844
+ onChange={setSelectedLabelNames}
1845
+ emptyLabel="All labels"
1846
+ />
1847
+ )}
1491
1848
  {showWorkspaceFilter ? (
1492
1849
  <FilterSelect
1493
1850
  label="Workspace"
@@ -1499,7 +1856,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1499
1856
  ) : null}
1500
1857
  {showGroupFilter ? (
1501
1858
  <FilterSelect
1502
- label="Group"
1859
+ label={groupLabel}
1503
1860
  value={selectedGroupId}
1504
1861
  options={groupOptions}
1505
1862
  activeClasses="border-purple-500/30 bg-purple-500/10 text-purple-400"
@@ -1510,10 +1867,10 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1510
1867
  label="Sort"
1511
1868
  value={sortBy}
1512
1869
  options={[
1513
- { value: "activity", label: "Activity" },
1870
+ { value: "activity", label: "Updated At" },
1514
1871
  { value: "identifier", label: "Ticket ID" },
1515
1872
  { value: "status", label: "Status" },
1516
- { value: "created", label: "Created" },
1873
+ { value: "created", label: "Created At" },
1517
1874
  ]}
1518
1875
  activeClasses="border-sky-500/30 bg-sky-500/10 text-sky-400"
1519
1876
  onChange={(value) => setSortBy(value as typeof sortBy)}
@@ -1526,17 +1883,6 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1526
1883
  >
1527
1884
  {sortDir === "desc" ? <ArrowDown size={12} /> : <ArrowUp size={12} />}
1528
1885
  </button>
1529
- <button
1530
- type="button"
1531
- className={`flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-[11px] font-medium transition-colors ${
1532
- hasActivity
1533
- ? "border-orange-500/30 bg-orange-500/10 text-orange-400"
1534
- : "border-[var(--card-border)] text-[var(--muted-foreground)] hover:bg-[var(--card-bg)]"
1535
- }`}
1536
- onClick={() => setHasActivity((v) => !v)}
1537
- >
1538
- My activity
1539
- </button>
1540
1886
  </div>
1541
1887
  </div>
1542
1888
 
@@ -1557,33 +1903,188 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1557
1903
  </div>
1558
1904
  ) : (
1559
1905
  <>
1560
- {/* Unified list: groups rendered inline at first-member position */}
1561
- {(() => {
1906
+ {groupByStatus ? (
1907
+ /* ── Status-grouped view ── */
1908
+ statusGroups.map((sg) => {
1909
+ const collapsed = collapsedStatusGroups.has(sg.status);
1910
+ return (
1911
+ <React.Fragment key={`sg-${sg.status}`}>
1912
+ <StatusGroupRow
1913
+ status={sg.status}
1914
+ categoryColor={STATUS_CATEGORY_COLORS[sg.category] ?? "bg-zinc-400"}
1915
+ count={sg.items.length}
1916
+ collapsed={collapsed}
1917
+ onToggle={() =>
1918
+ setCollapsedStatusGroups((prev) => {
1919
+ const next = new Set(prev);
1920
+ if (next.has(sg.status)) next.delete(sg.status);
1921
+ else next.add(sg.status);
1922
+ return next;
1923
+ })
1924
+ }
1925
+ />
1926
+ {!collapsed && (() => {
1927
+ const pendingSet = showGroupNamePrompt ? new Set(pendingGroupTaskIds) : null;
1928
+ const firstMemberToGroup = new Map<string, typeof taskGroups[number]>();
1929
+ for (const group of taskGroups) {
1930
+ const firstInStatus = sg.items.find((i) => group.task_ids.includes(i.id));
1931
+ if (firstInStatus) firstMemberToGroup.set(firstInStatus.id, group);
1932
+ }
1933
+ const pendingTickets = showGroupNamePrompt
1934
+ ? pendingGroupTaskIds
1935
+ .map((id) => sg.items.find((i) => i.id === id))
1936
+ .filter(Boolean)
1937
+ .map((i) => ({ id: i!.id, identifier: i!.identifier, title: i!.title, status: STATUS_LABELS[i!.status] ?? i!.status }))
1938
+ : [];
1939
+ const renderedGroups = new Set<string>();
1940
+
1941
+ return sg.items.map((item) => {
1942
+ if (pendingSet?.has(item.id)) {
1943
+ if (item.id === pendingGroupTargetId && showGroupNamePrompt) {
1944
+ return (
1945
+ <GroupNamePrompt
1946
+ key="__pending-group__"
1947
+ tickets={pendingTickets}
1948
+ onConfirm={handleCreateGroup}
1949
+ onCancel={() => {
1950
+ setShowGroupNamePrompt(false);
1951
+ setPendingGroupTaskIds([]);
1952
+ setPendingGroupTargetId(null);
1953
+ }}
1954
+ />
1955
+ );
1956
+ }
1957
+ return null;
1958
+ }
1959
+
1960
+ const group = firstMemberToGroup.get(item.id);
1961
+ if (group && !renderedGroups.has(group.id)) {
1962
+ renderedGroups.add(group.id);
1963
+ const groupItems = group.task_ids
1964
+ .map((id) => sg.items.find((i) => i.id === id))
1965
+ .filter(Boolean) as TrackerItem[];
1966
+ return (
1967
+ <React.Fragment key={`group-${group.id}`}>
1968
+ <FolderRow
1969
+ groupId={group.id}
1970
+ name={group.name}
1971
+ count={groupItems.length}
1972
+ collapsed={!!group.collapsed}
1973
+ selected={selectedGroupTaskGroupId === group.id}
1974
+ projectSlug={projectSlug}
1975
+ onToggleCollapse={() => updateGroup(group.id, { collapsed: !group.collapsed })}
1976
+ onSelect={() => pushSelection({ group: group.id, issue: null, run: null })}
1977
+ onUngroup={() => {
1978
+ void deleteGroup(group.id);
1979
+ if (selectedGroupTaskGroupId === group.id) {
1980
+ replaceSelection({ group: null });
1981
+ }
1982
+ }}
1983
+ />
1984
+ {!group.collapsed &&
1985
+ groupItems.map((gi, giIdx) => (
1986
+ <TicketRow
1987
+ key={gi.id}
1988
+ item={gi}
1989
+ selected={selectedItem?.id === gi.id}
1990
+ pinned={pinnedItemIds.has(gi.id)}
1991
+ activeAgents={issueActiveAgents.get(gi.id)}
1992
+ participants={participants}
1993
+ draggable
1994
+ multiSelected={multiSelectedItemIds.has(gi.id)}
1995
+ treeConnector={giIdx === groupItems.length - 1 ? "last" : "mid"}
1996
+ projectSlug={projectSlug}
1997
+ stats={issueStats.get(gi.id)}
1998
+ hideStatus
1999
+ estimate={metadataMap.get(gi.id)?.estimate}
2000
+ localLabels={metadataMap.get(gi.id)?.labels}
2001
+ labelDefinitions={labelDefinitions}
2002
+ allLabels={allLabels}
2003
+ onToggleLabel={(label) => handleItemToggleLabel(gi.id, label)}
2004
+ onAddLabel={handleItemAddLabel}
2005
+ onSelect={(event) => {
2006
+ if (event && (event.metaKey || event.ctrlKey)) {
2007
+ toggleItemMultiSelect(gi.id);
2008
+ } else {
2009
+ pushSelection({
2010
+ issue: gi.id,
2011
+ run: null,
2012
+ group: null,
2013
+ });
2014
+ }
2015
+ }}
2016
+ onTogglePin={() => togglePin(gi.id)}
2017
+ />
2018
+ ))}
2019
+ </React.Fragment>
2020
+ );
2021
+ }
2022
+
2023
+ if (groupedItemIds.has(item.id)) {
2024
+ return null;
2025
+ }
2026
+
2027
+ return (
2028
+ <TicketRow
2029
+ key={item.id}
2030
+ item={item}
2031
+ selected={selectedItem?.id === item.id}
2032
+ pinned={pinnedItemIds.has(item.id)}
2033
+ activeAgents={issueActiveAgents.get(item.id)}
2034
+ participants={participants}
2035
+ draggable
2036
+ multiSelected={multiSelectedItemIds.has(item.id)}
2037
+ projectSlug={projectSlug}
2038
+ stats={issueStats.get(item.id)}
2039
+ hideStatus
2040
+ estimate={metadataMap.get(item.id)?.estimate}
2041
+ localLabels={metadataMap.get(item.id)?.labels}
2042
+ labelDefinitions={labelDefinitions}
2043
+ allLabels={allLabels}
2044
+ onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
2045
+ onAddLabel={handleItemAddLabel}
2046
+ onSelect={(event) => {
2047
+ if (event && (event.metaKey || event.ctrlKey)) {
2048
+ toggleItemMultiSelect(item.id);
2049
+ } else {
2050
+ pushSelection({
2051
+ issue: item.id,
2052
+ run: null,
2053
+ group: null,
2054
+ });
2055
+ }
2056
+ }}
2057
+ onTogglePin={() => togglePin(item.id)}
2058
+ />
2059
+ );
2060
+ });
2061
+ })()}
2062
+ </React.Fragment>
2063
+ );
2064
+ })
2065
+ ) : (
2066
+ /* ── Flat/folder view ── */
2067
+ (() => {
1562
2068
  const pendingSet = showGroupNamePrompt ? new Set(pendingGroupTaskIds) : null;
1563
2069
 
1564
- // Build a map: itemId → group (for the first member of each group)
1565
2070
  const firstMemberToGroup = new Map<string, typeof taskGroups[number]>();
1566
2071
  for (const group of taskGroups) {
1567
- const firstInSort = sortedItems.find((i) => group.task_ids.includes(i.id));
2072
+ const firstInSort = labelFilteredItems.find((i) => group.task_ids.includes(i.id));
1568
2073
  if (firstInSort) firstMemberToGroup.set(firstInSort.id, group);
1569
2074
  }
1570
2075
 
1571
- // Pending group prompt: find insert position
1572
2076
  const pendingTickets = showGroupNamePrompt
1573
2077
  ? pendingGroupTaskIds
1574
- .map((id) => sortedItems.find((i) => i.id === id))
2078
+ .map((id) => labelFilteredItems.find((i) => i.id === id))
1575
2079
  .filter(Boolean)
1576
2080
  .map((i) => ({ id: i!.id, identifier: i!.identifier, title: i!.title, status: STATUS_LABELS[i!.status] ?? i!.status }))
1577
2081
  : [];
1578
2082
 
1579
- // Track which groups we've rendered
1580
2083
  const renderedGroups = new Set<string>();
1581
2084
  let looseIdx = 0;
1582
2085
 
1583
- return sortedItems.map((item) => {
1584
- // Skip pending tickets
2086
+ return labelFilteredItems.map((item) => {
1585
2087
  if (pendingSet?.has(item.id)) {
1586
- // Render prompt at target position
1587
2088
  if (item.id === pendingGroupTargetId && showGroupNamePrompt) {
1588
2089
  return (
1589
2090
  <GroupNamePrompt
@@ -1601,12 +2102,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1601
2102
  return null;
1602
2103
  }
1603
2104
 
1604
- // If this item is the first member of a group, render the group here
1605
2105
  const group = firstMemberToGroup.get(item.id);
1606
2106
  if (group && !renderedGroups.has(group.id)) {
1607
2107
  renderedGroups.add(group.id);
1608
2108
  const groupItems = group.task_ids
1609
- .map((id) => sortedItems.find((i) => i.id === id))
2109
+ .map((id) => labelFilteredItems.find((i) => i.id === id))
1610
2110
  .filter(Boolean) as TrackerItem[];
1611
2111
  return (
1612
2112
  <React.Fragment key={`group-${group.id}`}>
@@ -1643,6 +2143,13 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1643
2143
  multiSelected={multiSelectedItemIds.has(gi.id)}
1644
2144
  treeConnector={giIdx === groupItems.length - 1 ? "last" : "mid"}
1645
2145
  projectSlug={projectSlug}
2146
+ stats={issueStats.get(gi.id)}
2147
+ estimate={metadataMap.get(gi.id)?.estimate}
2148
+ localLabels={metadataMap.get(gi.id)?.labels}
2149
+ labelDefinitions={labelDefinitions}
2150
+ allLabels={allLabels}
2151
+ onToggleLabel={(label) => handleItemToggleLabel(gi.id, label)}
2152
+ onAddLabel={handleItemAddLabel}
1646
2153
  onSelect={(event) => {
1647
2154
  if (event && (event.metaKey || event.ctrlKey)) {
1648
2155
  toggleItemMultiSelect(gi.id);
@@ -1661,13 +2168,11 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1661
2168
  );
1662
2169
  }
1663
2170
 
1664
- // Skip grouped items (already rendered with their group)
1665
2171
  if (groupedItemIds.has(item.id)) return null;
1666
2172
 
1667
- // Loose ticket
1668
2173
  const currentLooseIdx = looseIdx++;
1669
2174
  const prevLoose = currentLooseIdx > 0
1670
- ? sortedItems.filter((i) => !groupedItemIds.has(i.id) && (!pendingSet || !pendingSet.has(i.id)))[currentLooseIdx - 1]
2175
+ ? labelFilteredItems.filter((i) => !groupedItemIds.has(i.id) && (!pendingSet || !pendingSet.has(i.id)))[currentLooseIdx - 1]
1671
2176
  : null;
1672
2177
  return (
1673
2178
  <React.Fragment key={item.id}>
@@ -1685,6 +2190,13 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1685
2190
  draggable
1686
2191
  multiSelected={multiSelectedItemIds.has(item.id)}
1687
2192
  projectSlug={projectSlug}
2193
+ stats={issueStats.get(item.id)}
2194
+ estimate={metadataMap.get(item.id)?.estimate}
2195
+ localLabels={metadataMap.get(item.id)?.labels}
2196
+ labelDefinitions={labelDefinitions}
2197
+ allLabels={allLabels}
2198
+ onToggleLabel={(label) => handleItemToggleLabel(item.id, label)}
2199
+ onAddLabel={handleItemAddLabel}
1688
2200
  onSelect={(event) => {
1689
2201
  if (event && (event.metaKey || event.ctrlKey)) {
1690
2202
  toggleItemMultiSelect(item.id);
@@ -1701,7 +2213,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1701
2213
  </React.Fragment>
1702
2214
  );
1703
2215
  });
1704
- })()}
2216
+ })())}
1705
2217
  {hasMore ? (
1706
2218
  <div
1707
2219
  ref={sentinelRef}
@@ -1716,11 +2228,23 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1716
2228
  count={multiSelectedItemIds.size}
1717
2229
  onGroup={handleMultiSelectGroup}
1718
2230
  onClear={() => setMultiSelectedItemIds(new Set())}
2231
+ onBulkRecap={handleBulkRecap}
2232
+ onBulkPrompt={handleBulkPrompt}
2233
+ onBulkEstimate={handleBulkEstimate}
2234
+ onBulkAddLabel={handleBulkAddLabel}
2235
+ onBulkRemoveLabel={handleBulkRemoveLabel}
2236
+ onBulkStatus={handleBulkStatus}
2237
+ statusOptions={itemStatusOptions}
2238
+ participants={participants}
2239
+ labels={allLabels}
2240
+ onCreateLabel={handleCreateLabel}
2241
+ selectedMetadata={selectedMetadata}
2242
+ statusUpdating={bulkStatusUpdating}
1719
2243
  />
1720
2244
  </div>
1721
2245
  <DragOverlay dropAnimation={null}>
1722
2246
  {dragActiveId && (() => {
1723
- const dragItem = sortedItems.find((i) => i.id === dragActiveId);
2247
+ const dragItem = sortedItemsRef.current.find((i) => i.id === dragActiveId);
1724
2248
  if (!dragItem) return null;
1725
2249
  return (
1726
2250
  <div className="flex items-center gap-3 rounded-lg border border-[var(--primary)]/30 bg-[var(--card-bg)] px-4 py-2.5 text-sm shadow-xl backdrop-blur-sm">
@@ -1737,7 +2261,7 @@ export default function TrackerBoard({ trackerType, projectId, projectSlug, init
1737
2261
  </DndContext>
1738
2262
  </div>
1739
2263
 
1740
- <ResizeHandle onResize={(delta) => setTicketPanelWidth((w) => { const next = Math.max(180, Math.min(600, w + delta)); persistLinearTicketPanelWidth(next); return next; })} />
2264
+ <ResizeHandle onResize={(delta) => setTicketPanelWidth((w) => { const next = Math.max(280, Math.min(960, w + delta)); persistLinearTicketPanelWidth(next); return next; })} />
1741
2265
 
1742
2266
  {showRunScripts ? (
1743
2267
  <div