@taskmark/ui 0.2.4 → 0.2.6

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 (215) hide show
  1. package/README.md +46 -10
  2. package/app/api/taskmark-reload/route.ts +103 -0
  3. package/app/board/page.tsx +6 -4
  4. package/app/layout.tsx +2 -0
  5. package/app/setup/page.tsx +4 -1
  6. package/bin/lib/resolve-board.mjs +50 -1
  7. package/bin/lib/watch-board-markdown.mjs +65 -0
  8. package/bin/taskmark.js +310 -67
  9. package/components/board/app-bar.tsx +31 -34
  10. package/components/board/board-dev-reloader.tsx +49 -0
  11. package/components/board/epic-list.tsx +2 -4
  12. package/components/board/overall-work-items-list.tsx +2 -1
  13. package/components/board/static-board-app.tsx +0 -1
  14. package/components/board/story-list.tsx +2 -1
  15. package/components/board/task-list.tsx +2 -1
  16. package/components/board/work-item-sheet.tsx +15 -2
  17. package/components/board/work-items-list.tsx +2 -2
  18. package/components/setup/setup-wizard.tsx +2 -6
  19. package/dist/prod-next/BUILD_ID +1 -0
  20. package/dist/{standalone/.next → prod-next}/app-path-routes-manifest.json +3 -2
  21. package/dist/{standalone/.next → prod-next}/build-manifest.json +3 -3
  22. package/dist/prod-next/export-marker.json +6 -0
  23. package/dist/prod-next/images-manifest.json +68 -0
  24. package/dist/prod-next/next-minimal-server.js.nft.json +1 -0
  25. package/dist/prod-next/next-server.js.nft.json +1 -0
  26. package/dist/{standalone/.next → prod-next}/prerender-manifest.json +27 -3
  27. package/dist/{standalone/.next → prod-next}/react-loadable-manifest.json +2 -2
  28. package/dist/prod-next/required-server-files.js +337 -0
  29. package/dist/{standalone/.next → prod-next}/required-server-files.json +0 -7
  30. package/dist/{standalone/.next → prod-next}/routes-manifest.json +6 -0
  31. package/dist/prod-next/server/app/_global-error/page.js +32 -0
  32. package/dist/prod-next/server/app/_global-error/page.js.nft.json +1 -0
  33. package/dist/prod-next/server/app/_global-error/page_client-reference-manifest.js +1 -0
  34. package/dist/{standalone/.next → prod-next}/server/app/_global-error.html +1 -1
  35. package/dist/{standalone/.next → prod-next}/server/app/_global-error.rsc +1 -1
  36. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_full.segment.rsc +1 -1
  37. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  38. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  39. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_head.segment.rsc +1 -1
  40. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_index.segment.rsc +1 -1
  41. package/dist/{standalone/.next → prod-next}/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  42. package/dist/prod-next/server/app/_not-found/page.js +2 -0
  43. package/dist/prod-next/server/app/_not-found/page.js.nft.json +1 -0
  44. package/dist/prod-next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  45. package/dist/prod-next/server/app/_not-found.html +1 -0
  46. package/dist/prod-next/server/app/_not-found.rsc +21 -0
  47. package/dist/prod-next/server/app/_not-found.segments/_full.segment.rsc +21 -0
  48. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_head.segment.rsc +1 -1
  49. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_index.segment.rsc +5 -4
  50. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  51. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  52. package/dist/{standalone/.next → prod-next}/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  53. package/dist/prod-next/server/app/api/taskmark-reload/route.js +1 -0
  54. package/dist/prod-next/server/app/api/taskmark-reload/route.js.nft.json +1 -0
  55. package/dist/prod-next/server/app/api/taskmark-reload/route_client-reference-manifest.js +1 -0
  56. package/dist/{standalone/.next → prod-next}/server/app/board/page.js +14 -14
  57. package/dist/prod-next/server/app/board/page.js.nft.json +1 -0
  58. package/dist/prod-next/server/app/board/page_client-reference-manifest.js +1 -0
  59. package/dist/{standalone/.next → prod-next}/server/app/favicon.ico/route.js +1 -1
  60. package/dist/prod-next/server/app/favicon.ico/route.js.nft.json +1 -0
  61. package/dist/prod-next/server/app/page.js +2 -0
  62. package/dist/prod-next/server/app/page.js.nft.json +1 -0
  63. package/dist/prod-next/server/app/page_client-reference-manifest.js +1 -0
  64. package/dist/prod-next/server/app/setup/page.js +2 -0
  65. package/dist/prod-next/server/app/setup/page.js.nft.json +1 -0
  66. package/dist/prod-next/server/app/setup/page_client-reference-manifest.js +1 -0
  67. package/dist/prod-next/server/app/setup.html +1 -0
  68. package/dist/prod-next/server/app/setup.meta +17 -0
  69. package/dist/{standalone/.next/server/app/_not-found.rsc → prod-next/server/app/setup.rsc} +17 -15
  70. package/dist/{standalone/.next/server/app/_not-found.segments → prod-next/server/app/setup.segments}/_full.segment.rsc +17 -15
  71. package/dist/prod-next/server/app/setup.segments/_head.segment.rsc +6 -0
  72. package/dist/prod-next/server/app/setup.segments/_index.segment.rsc +8 -0
  73. package/dist/prod-next/server/app/setup.segments/_tree.segment.rsc +5 -0
  74. package/dist/prod-next/server/app/setup.segments/setup/__PAGE__.segment.rsc +6 -0
  75. package/dist/prod-next/server/app/setup.segments/setup.segment.rsc +5 -0
  76. package/dist/{standalone/.next → prod-next}/server/app-paths-manifest.json +3 -2
  77. package/dist/{standalone/.next → prod-next}/server/chunks/319.js +1 -1
  78. package/dist/{standalone/.next → prod-next}/server/chunks/490.js +2 -2
  79. package/dist/prod-next/server/chunks/57.js +19 -0
  80. package/dist/prod-next/server/chunks/616.js +1 -0
  81. package/dist/prod-next/server/chunks/708.js +1 -0
  82. package/dist/prod-next/server/chunks/724.js +1 -0
  83. package/dist/{standalone/.next/server/chunks/445.js → prod-next/server/chunks/741.js} +2 -2
  84. package/dist/prod-next/server/functions-config-manifest.json +6 -0
  85. package/dist/prod-next/server/interception-route-rewrite-manifest.js +1 -0
  86. package/dist/{standalone/.next → prod-next}/server/middleware-build-manifest.js +1 -1
  87. package/dist/prod-next/server/middleware-react-loadable-manifest.js +1 -0
  88. package/dist/prod-next/server/pages/404.html +1 -0
  89. package/dist/{standalone/.next → prod-next}/server/pages/500.html +1 -1
  90. package/dist/prod-next/server/server-reference-manifest.js +1 -0
  91. package/dist/prod-next/server/server-reference-manifest.json +1 -0
  92. package/dist/prod-next/static/chunks/51.e9139a9ea6eb36b9.js +1 -0
  93. package/dist/{standalone/.next/static/chunks/781-f9f201ddc8c8591a.js → prod-next/static/chunks/613-6f794154d28bb75a.js} +1 -1
  94. package/dist/prod-next/static/chunks/app/_global-error/page-d34451c04262dd7d.js +1 -0
  95. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-d34451c04262dd7d.js +1 -0
  96. package/dist/prod-next/static/chunks/app/board/page-cd1d9be0c0127225.js +1 -0
  97. package/dist/prod-next/static/chunks/app/layout-856e8a282e69e7d0.js +1 -0
  98. package/dist/prod-next/static/chunks/app/page-d34451c04262dd7d.js +1 -0
  99. package/dist/prod-next/static/chunks/app/setup/page-c3003359e8becc84.js +1 -0
  100. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-d34451c04262dd7d.js +1 -0
  101. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-d34451c04262dd7d.js +1 -0
  102. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-d34451c04262dd7d.js +1 -0
  103. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-d34451c04262dd7d.js +1 -0
  104. package/dist/{standalone/.next/static/chunks/webpack-b59eaf276b7fb38f.js → prod-next/static/chunks/webpack-bfe8992962004e2b.js} +1 -1
  105. package/dist/prod-next/static/sAWr5ATVuqk6Wqs18kAWs/_buildManifest.js +1 -0
  106. package/dist/public/taskmark-snapshot.json +1 -0
  107. package/lib/display-path.ts +6 -0
  108. package/lib/taskmark/autoconfig.ts +54 -3
  109. package/lib/taskmark/dev-reload-token.ts +5 -0
  110. package/lib/taskmark/discover.ts +2 -1
  111. package/lib/taskmark/project-label.ts +3 -2
  112. package/lib/taskmark/validate.ts +4 -4
  113. package/lib/taskmark/workspace-mode.ts +24 -0
  114. package/lib/taskmark/workspace.ts +5 -2
  115. package/next.config.ts +3 -8
  116. package/package.json +7 -4
  117. package/public/taskmark-snapshot.json +1 -1
  118. package/scripts/build-static.mjs +10 -1
  119. package/scripts/prepare-standalone.mjs +53 -20
  120. package/dist/standalone/.next/BUILD_ID +0 -1
  121. package/dist/standalone/.next/server/app/_global-error/page.js +0 -32
  122. package/dist/standalone/.next/server/app/_global-error/page.js.nft.json +0 -1
  123. package/dist/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +0 -1
  124. package/dist/standalone/.next/server/app/_not-found/page.js +0 -2
  125. package/dist/standalone/.next/server/app/_not-found/page.js.nft.json +0 -1
  126. package/dist/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  127. package/dist/standalone/.next/server/app/_not-found.html +0 -1
  128. package/dist/standalone/.next/server/app/board/page.js.nft.json +0 -1
  129. package/dist/standalone/.next/server/app/board/page_client-reference-manifest.js +0 -1
  130. package/dist/standalone/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  131. package/dist/standalone/.next/server/app/page.js +0 -2
  132. package/dist/standalone/.next/server/app/page.js.nft.json +0 -1
  133. package/dist/standalone/.next/server/app/page_client-reference-manifest.js +0 -1
  134. package/dist/standalone/.next/server/app/setup/page.js +0 -2
  135. package/dist/standalone/.next/server/app/setup/page.js.nft.json +0 -1
  136. package/dist/standalone/.next/server/app/setup/page_client-reference-manifest.js +0 -1
  137. package/dist/standalone/.next/server/chunks/164.js +0 -1
  138. package/dist/standalone/.next/server/chunks/57.js +0 -19
  139. package/dist/standalone/.next/server/chunks/570.js +0 -1
  140. package/dist/standalone/.next/server/chunks/666.js +0 -1
  141. package/dist/standalone/.next/server/functions-config-manifest.json +0 -4
  142. package/dist/standalone/.next/server/middleware-react-loadable-manifest.js +0 -1
  143. package/dist/standalone/.next/server/pages/404.html +0 -1
  144. package/dist/standalone/.next/server/server-reference-manifest.js +0 -1
  145. package/dist/standalone/.next/server/server-reference-manifest.json +0 -1
  146. package/dist/standalone/.next/static/chunks/211.a43663747d668728.js +0 -1
  147. package/dist/standalone/.next/static/chunks/app/_global-error/page-82d456ade9f47021.js +0 -1
  148. package/dist/standalone/.next/static/chunks/app/board/page-6db8dec814516c28.js +0 -1
  149. package/dist/standalone/.next/static/chunks/app/layout-3745e06d87691845.js +0 -1
  150. package/dist/standalone/.next/static/chunks/app/page-82d456ade9f47021.js +0 -1
  151. package/dist/standalone/.next/static/chunks/app/setup/page-8a54c6f26633bdca.js +0 -1
  152. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-82d456ade9f47021.js +0 -1
  153. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-82d456ade9f47021.js +0 -1
  154. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-82d456ade9f47021.js +0 -1
  155. package/dist/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-82d456ade9f47021.js +0 -1
  156. package/dist/standalone/.next/static/jm3kxf8c6qGe0cYKCktaO/_buildManifest.js +0 -1
  157. package/dist/standalone/node_modules/next/dist/compiled/jest-worker/processChild.js +0 -1
  158. package/dist/standalone/node_modules/next/dist/compiled/jest-worker/threadChild.js +0 -1
  159. package/dist/standalone/node_modules/next/dist/server/lib/start-server.js +0 -494
  160. package/dist/standalone/node_modules/next/dist/server/next-server.js +0 -1429
  161. package/dist/standalone/node_modules/next/dist/server/next.js +0 -455
  162. package/dist/standalone/node_modules/next/dist/server/require-hook.js +0 -82
  163. package/dist/standalone/node_modules/next/dist/server/route-modules/app-page/module.compiled.js +0 -36
  164. package/dist/standalone/node_modules/next/dist/server/route-modules/pages/module.compiled.js +0 -20
  165. package/dist/standalone/node_modules/styled-jsx/index.js +0 -1
  166. package/dist/standalone/node_modules/styled-jsx/package.json +0 -132
  167. package/dist/standalone/node_modules/styled-jsx/style.js +0 -1
  168. package/dist/standalone/package.json +0 -77
  169. package/dist/standalone/public/taskmark-snapshot.json +0 -1
  170. package/dist/standalone/server.js +0 -44
  171. /package/dist/{standalone/.next → prod-next}/package.json +0 -0
  172. /package/dist/{standalone/.next → prod-next}/server/app/_global-error.meta +0 -0
  173. /package/dist/{standalone/.next → prod-next}/server/app/_not-found.meta +0 -0
  174. /package/dist/{standalone/.next → prod-next}/server/app/favicon.ico.body +0 -0
  175. /package/dist/{standalone/.next → prod-next}/server/app/favicon.ico.meta +0 -0
  176. /package/dist/{standalone/.next → prod-next}/server/chunks/318.js +0 -0
  177. /package/dist/{standalone/.next → prod-next}/server/middleware-manifest.json +0 -0
  178. /package/dist/{standalone/.next → prod-next}/server/next-font-manifest.js +0 -0
  179. /package/dist/{standalone/.next → prod-next}/server/next-font-manifest.json +0 -0
  180. /package/dist/{standalone/.next → prod-next}/server/pages-manifest.json +0 -0
  181. /package/dist/{standalone/.next → prod-next}/server/prefetch-hints.json +0 -0
  182. /package/dist/{standalone/.next → prod-next}/server/webpack-runtime.js +0 -0
  183. /package/dist/{standalone/.next → prod-next}/static/chunks/4bd1b696-deb4a0a1da1923b0.js +0 -0
  184. /package/dist/{standalone/.next → prod-next}/static/chunks/669-8103441c67b185da.js +0 -0
  185. /package/dist/{standalone/.next → prod-next}/static/chunks/701-df3ee5f1cf837b1a.js +0 -0
  186. /package/dist/{standalone/.next → prod-next}/static/chunks/794-25668765560cb197.js +0 -0
  187. /package/dist/{standalone/.next → prod-next}/static/chunks/app/_not-found/page-0b3785af737e7968.js +0 -0
  188. /package/dist/{standalone/.next → prod-next}/static/chunks/framework-b29f9083d3cda3b2.js +0 -0
  189. /package/dist/{standalone/.next → prod-next}/static/chunks/main-app-bfb36455d24b3e5a.js +0 -0
  190. /package/dist/{standalone/.next → prod-next}/static/chunks/main-bb33c46a9c25dee8.js +0 -0
  191. /package/dist/{standalone/.next → prod-next}/static/chunks/next/dist/client/components/builtin/global-error-dc53ab29e0491fe4.js +0 -0
  192. /package/dist/{standalone/.next → prod-next}/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  193. /package/dist/{standalone/.next → prod-next}/static/css/2e6ec4c80894e3c0.css +0 -0
  194. /package/dist/{standalone/.next → prod-next}/static/css/c593627ceef17a4b.css +0 -0
  195. /package/dist/{standalone/.next → prod-next}/static/media/36966cca54120369-s.p.woff2 +0 -0
  196. /package/dist/{standalone/.next → prod-next}/static/media/982ceffe7b733b3b-s.p.woff2 +0 -0
  197. /package/dist/{standalone/.next → prod-next}/static/media/b7387a63dd068245-s.woff2 +0 -0
  198. /package/dist/{standalone/.next → prod-next}/static/media/b8bfb68ab9ab617c-s.woff2 +0 -0
  199. /package/dist/{standalone/.next → prod-next}/static/media/e1aab0933260df4d-s.woff2 +0 -0
  200. /package/dist/{standalone/.next/static/jm3kxf8c6qGe0cYKCktaO → prod-next/static/sAWr5ATVuqk6Wqs18kAWs}/_ssgManifest.js +0 -0
  201. /package/dist/{standalone/public → public}/apple-touch-icon.png +0 -0
  202. /package/dist/{standalone/public → public}/favicon-96x96.png +0 -0
  203. /package/dist/{standalone/public → public}/favicon.ico +0 -0
  204. /package/dist/{standalone/public → public}/favicon.svg +0 -0
  205. /package/dist/{standalone/public → public}/file.svg +0 -0
  206. /package/dist/{standalone/public → public}/globe.svg +0 -0
  207. /package/dist/{standalone/public → public}/next.svg +0 -0
  208. /package/dist/{standalone/public → public}/og/og-default.png +0 -0
  209. /package/dist/{standalone/public → public}/site.webmanifest +0 -0
  210. /package/dist/{standalone/public → public}/tm_dark.png +0 -0
  211. /package/dist/{standalone/public → public}/tm_light.png +0 -0
  212. /package/dist/{standalone/public → public}/vercel.svg +0 -0
  213. /package/dist/{standalone/public → public}/web-app-manifest-192x192.png +0 -0
  214. /package/dist/{standalone/public → public}/web-app-manifest-512x512.png +0 -0
  215. /package/dist/{standalone/public → public}/window.svg +0 -0
@@ -0,0 +1 @@
1
+ {"version":1,"builtAt":"2026-08-14T15:09:02.362Z","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"projects":[{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}],"epics":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epics":[{"id":"E-009","title":"General","status":"in_progress","priority":"medium","size":"—","points":52,"estimateMinutes":4105,"actualMinutes":2911,"actualMs":174681000,"tags":["general"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":22,"doneWorkItemCount":22,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-001","title":"Motor de exercícios","status":"in_progress","priority":"medium","size":"—","points":40,"estimateMinutes":1555,"actualMinutes":1154,"actualMs":69282000,"tags":["module","motor-exercicios"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":23,"doneWorkItemCount":23,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-002","title":"PSE","status":"done","priority":"medium","size":"—","points":12,"estimateMinutes":1223,"actualMinutes":557,"actualMs":33427000,"tags":["module","pse"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-29T16:54:42Z","workItemCount":6,"doneWorkItemCount":6,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-003","title":"Wellness","status":"done","priority":"medium","size":"—","points":8,"estimateMinutes":685,"actualMinutes":562,"actualMs":33743000,"tags":["module","wellness"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-29T16:54:42Z","workItemCount":4,"doneWorkItemCount":4,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-004","title":"Planeamento","status":"in_progress","priority":"medium","size":"—","points":29,"estimateMinutes":360,"actualMinutes":430,"actualMs":25820000,"tags":["module","planeamento"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":13,"doneWorkItemCount":11,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-005","title":"Lineup","status":"in_progress","priority":"medium","size":"—","points":5,"estimateMinutes":120,"actualMinutes":1,"actualMs":60000,"tags":["module","lineup"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-006","title":"Website","status":"in_progress","priority":"medium","size":"—","points":7,"estimateMinutes":70,"actualMinutes":44,"actualMs":2673000,"tags":["module","website"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":5,"doneWorkItemCount":5,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-007","title":"Admin dashboard","status":"done","priority":"medium","size":"—","points":39,"estimateMinutes":1315,"actualMinutes":1761,"actualMs":105691000,"tags":["module","admin","dashboard"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-11T16:08:09Z","workItemCount":18,"doneWorkItemCount":18,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-008","title":"Perfil de Utilizadores e Equipas","status":"done","priority":"medium","size":"—","points":4,"estimateMinutes":75,"actualMinutes":61,"actualMs":3667000,"tags":["module","perfil","utilizadores","equipas"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-03T15:57:46Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-010","title":"Pagamentos","status":"done","priority":"high","size":"—","points":34,"estimateMinutes":5302,"actualMinutes":5282,"actualMs":316969000,"tags":["module","pagamentos","facturacao","stripe","billing"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":15,"doneWorkItemCount":15,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-011","title":"Backup do produto","status":"done","priority":"high","size":"—","points":16,"estimateMinutes":585,"actualMinutes":486,"actualMs":29192000,"tags":["ops","backup","mongo","s3","infra"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-11T16:08:09Z","workItemCount":8,"doneWorkItemCount":8,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"E-012","title":"Auth UI — login, registo e convites de organização","status":"done","priority":"high","size":"—","points":64,"estimateMinutes":2160,"actualMinutes":121,"actualMs":7297335,"tags":["auth","auth0","login","signup","convites","sendgrid","ui","shadcn","organizacoes"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:07:19Z","workItemCount":29,"doneWorkItemCount":20,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/epic.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"workItemsView":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"rows":[{"kind":"story","id":"S-007","title":"Exportar calendário do planeamento em PDF (mensal e semana)","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":22,"actualMs":1339000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","pdf","export","calendar","preview"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":1,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-018","title":"Nova UI de login (shadcn login-02) com Auth0","status":"done","priority":"high","size":"XL","points":21,"estimateMinutes":625,"actualMinutes":32,"actualMs":1957934,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","login","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:12:30Z","workItemCount":10,"doneWorkItemCount":8,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-020","title":"Fluxo de convite para organização (email, registo, login e confirmação)","status":"done","priority":"critical","size":"XL","points":35,"estimateMinutes":1225,"actualMinutes":86,"actualMs":5219401,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","convites","sendgrid","organizacoes","signup","login"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T15:22:58Z","workItemCount":14,"doneWorkItemCount":7,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-019","title":"Nova UI de registo normal (shadcn signup-02) com Auth0","status":"done","priority":"high","size":"L","points":8,"estimateMinutes":310,"actualMinutes":2,"actualMs":120000,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","signup","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-054","title":"Jogador — campos Número e Pé preferencial (lista e export lineup)","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-005","epicTitle":"Lineup","tags":["lineup","jogador","plantel","export","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:07:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-053","title":"Intensidade do treino — níveis 1–10 e slider no formulário","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","treino","intensidade","slider","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:06:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-052","title":"Contador de caracteres na descrição e materiais do exercício (aviso soft)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":60000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["ui","motor-exercicios","editor","description","materials","character-limit"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:05:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-051","title":"Melhorias UI — badge Novo no marketplace, paginação no footer e labels lineup","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["ui","motor-exercicios","marketplace","pagination","lineup","i18n","microciclo","planeamento"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:04:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-050","title":"Código sequencial UT/TS nos treinos da época/equipa","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":9,"actualMs":542000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","treino","codigo","i18n","reporte-treino"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:01:25Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-055","title":"Open Graph — usar og.png como imagem Facebook no site e na app","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"epicId":"E-009","epicTitle":"General","tags":["seo","opengraph","facebook","metadata","website","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-056","title":"Google Analytics — gtag na app e no site","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"epicId":"E-009","epicTitle":"General","tags":["analytics","google-analytics","gtag","website","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-057","title":"Melhorar SEO do website e da app (titles, OG, robots, schema)","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":41,"actualMs":2482000,"epicId":"E-006","epicTitle":"Website","tags":["seo","metadata","opengraph","website","frontend","robots","accessibility"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-027","title":"Editor — copy/paste de seta/curva perde pontos de controlo da curvatura","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["bug","motor-exercicios","editor","copy-paste","arrow","curve"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:27:50Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-028","title":"Setup/wizard — país não pré-preenche ao escolher equipa do datacenter","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"epicId":"E-009","epicTitle":"General","tags":["bug","setup","onboarding","wizard","country-picker","datacenter"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:27:50Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-036","title":"PSE — skeleton em loop numa semana sem treinos","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":78,"actualMinutes":1,"actualMs":88000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","rpe","loading","empty-state"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T16:20:40Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-030","title":"Modal Completa o teu perfil aparece no setup/onboarding wizard","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["perfil","setup","onboarding","dialog","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:08:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-015","title":"Backup automático diário Mongo → S3 (02:00)","status":"done","priority":"high","size":"L","points":10,"estimateMinutes":515,"actualMinutes":482,"actualMs":28952000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","backup","mongo","s3","cron"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-11T16:08:09Z","workItemCount":3,"doneWorkItemCount":3,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-066","title":"Script CLI para copiar equipa entre organizações","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2358000,"epicId":"E-009","epicTitle":"General","tags":["ops","mongo","script","team","migration"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T16:08:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-017","title":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","status":"done","priority":"critical","size":"XL","points":24,"estimateMinutes":1390,"actualMinutes":1028,"actualMs":61734000,"epicId":"E-009","epicTitle":"General","tags":["organizacoes","auth0","migracao","setup-wizard","sidebar","401","404","multi-tenant"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","workItemCount":8,"doneWorkItemCount":8,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-034","title":"Resposta admin fecha ticket em vez de passar a Em progresso","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":204000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","support","tickets"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T11:15:47Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-064","title":"Script para apagar wellness/RPE legacy do Mongo","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":50,"actualMinutes":2,"actualMs":153000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","mongo","cleanup","wellness","rpe","backup"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-10T23:47:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-009","title":"Gerir autores de blog posts no admin (incluindo autores manuais)","status":"done","priority":"medium","size":"XL","points":12,"estimateMinutes":705,"actualMinutes":706,"actualMs":42366000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","website","blog","autores"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-10T05:54:44.000Z","workItemCount":5,"doneWorkItemCount":5,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-027","title":"Exportar plantel — documento estilo relatório de unidade de treino","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"epicId":"E-005","epicTitle":"Lineup","tags":["lineup","plantel","export","pdf","report","print"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-05T00:17:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-016","title":"Editor — copy/paste não funciona com múltiplos elementos seleccionados","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","editor","copy-paste","multi-select","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-05T00:07:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-005","title":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":11,"actualMs":685000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","planeamento","categoria","fase-tipo","multi-select"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-05T00:00:08Z","workItemCount":1,"doneWorkItemCount":1,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-006","title":"Duplicar exercício com confirmação e sufixo (copia)","status":"done","priority":"medium","size":"M","points":4,"estimateMinutes":20,"actualMinutes":18,"actualMs":1127000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","duplicate","modal"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-05T00:00:08Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-026","title":"/pub/media/*.woff2 404 ao exportar/renderizar exercícios","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":620000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","fonts","pub","media-render"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T23:59:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-001","title":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","status":"done","priority":"medium","size":"M","points":5,"estimateMinutes":570,"actualMinutes":561,"actualMs":33710000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","ui","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-04T23:59:54Z","workItemCount":3,"doneWorkItemCount":3,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-048","title":"Guardar exercício — media em background (imagem primeiro, depois vídeo e claro)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","media","preview","performance","api","background"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T23:55:40Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-047","title":"Lista vertical — thumbnail a 100% do cartão sem cortes","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2344000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","layout","thumbnail","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T17:35:36Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-046","title":"Lista horizontal — thumbnail a preencher a coluna sem espaços em branco","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":15,"actualMinutes":13,"actualMs":780000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","layout","thumbnail","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T16:55:31Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-030","title":"Lista de exercícios — sem pasta primeiro, pastas por baixo","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":0,"actualMs":16000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","folders","ux","ordering"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T16:16:35Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-029","title":"Lista de exercícios paginada (pastas lazy + pesquisa plana)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":7,"actualMs":475000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","pagination","folders","performance","search"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T15:18:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-012","title":"Página de definições de facturação por conta (formulário + sync Stripe)","status":"done","priority":"high","size":"XL","points":27,"estimateMinutes":4320,"actualMinutes":4320,"actualMs":259200000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","settings","billing"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":9,"doneWorkItemCount":9,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-013","title":"Dialog CTA quando subscrição activa sem dados de facturação","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":502,"actualMinutes":482,"actualMs":28969000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","ux","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-014","title":"Listagem de facturas Stripe na página de facturação","status":"done","priority":"medium","size":"S","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","invoices"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":1,"doneWorkItemCount":1,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-020","title":"Picker de países — lista filtrada ao reabrir e bandeiras","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["ui","forms","countries","combobox","setup","onboarding","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-021","title":"Picker de países no modal de facturação — clique não selecciona","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["ui","forms","countries","combobox","dialog","billing","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-025","title":"Utilizadores duplicados na lista admin (mesmo auth0Sub)","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":60,"actualMinutes":59,"actualMs":3597000,"epicId":"E-008","epicTitle":"Perfil de Utilizadores e Equipas","tags":["perfil","admin","utilizadores","auth0","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-016","title":"CLI NPM para backup manual com inquirer","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":20,"actualMinutes":1,"actualMs":87000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","backup","cli","inquirer","npm"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-03","completedAt":"2026-08-03T15:44:22Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-024","title":"Planeamento — MD-x em falta quando jogos estão a 7 dias","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":252000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","match-day","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:45:12Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-023","title":"Planeamento — tipo de jogo amigável não é gravado","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","jogo","match-type","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:26:10Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-022","title":"Exercise editor — PageHeader maximum update depth exceeded","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":295000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","editor","page-header","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:16:55Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-014","title":"Frontend build falha (zodResolver SeasonSettings) e avisos ESLint","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"epicId":"E-009","epicTitle":"General","tags":["frontend","build","eslint","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:54:42Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-011","title":"Mostrar meso e micro ciclos no calendário de planeamento","status":"done","priority":"high","size":"XL","points":8,"estimateMinutes":80,"actualMinutes":317,"actualMs":19076000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","calendar","periodizacao","meso-ciclo","micro-ciclo","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:47:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-013","title":"Campo livre aparece em branco no relatório de unidade de treino","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":206000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","training-report","exercises","field-preset","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:05:20Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-012","title":"Bola teleporta ao associar a jogador durante animação","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":187000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","animacao","bola","attachment","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T11:14:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-011","title":"Texto no vídeo do exercício usa fonte diferente do portal","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","video","font","export","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-29T10:38:42Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-008","title":"CRUD de tags e categorias dos artigos do website no admin","status":"done","priority":"medium","size":"L","points":5,"estimateMinutes":25,"actualMinutes":480,"actualMs":28800000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","website","tags","categorias","artigos","crud"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-29T07:41:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-022","title":"Suavizar profundidade do layout de campo 3D","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","field","perspective","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T09:37:11Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-010","title":"Wellness manual no planeamento exige treino/jogo","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":56000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","planeamento","i18n","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T09:00:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-021","title":"Hero — embed Loom com moldura responsiva","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":54000,"epicId":"E-006","epicTitle":"Website","tags":["website","hero"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T08:32:22Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-004","title":"Artigos em destaque — imagem sem cover inflaciona os cartões","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":69000,"epicId":"E-006","epicTitle":"Website","tags":["website","blog","featured","images","cover","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-008","title":"Artigos website — restaurar bullets de listagem (disc)","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"epicId":"E-006","epicTitle":"Website","tags":["website","artigos","css","lists","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-009","title":"Artigos website — imagens a 100% da largura do conteúdo","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"epicId":"E-006","epicTitle":"Website","tags":["website","artigos","images","css"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-003","title":"Avatar no perfil não sincroniza no Auth0 (usar proxy frontend em vez de S3)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":1,"actualMs":70000,"epicId":"E-008","epicTitle":"Perfil de Utilizadores e Equipas","tags":["perfil","avatar","auth0","s3","proxy","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:44:32Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-020","title":"Expanded layout — botão Voltar com hit target decente","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":66000,"epicId":"E-004","epicTitle":"Planeamento","tags":["ui","ux","expanded-layout","planeamento"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T07:09:36Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-009","title":"Export PDF semana omite jogos no domingo (filtro to date-only)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":70000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","pdf","export","games","api"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T08:28:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-010","title":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","status":"done","priority":"high","size":"XL","points":20,"estimateMinutes":580,"actualMinutes":572,"actualMs":34321000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","users","teams","tabs","dashboard"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T07:54:31Z","workItemCount":9,"doneWorkItemCount":9,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-002","title":"Sheet criar jogo no planeamento mostra i18n em inglês","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":10,"actualMinutes":1,"actualMs":60000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","i18n","bug","sheet","jogo"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-27T07:53:18Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-004","title":"Reporte treino — text-gray-400 para text-gray-600","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":180000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","ui","reporte-treino","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-27T07:53:18Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-008","title":"Equipas duplicadas no setup/onboarding — retry e guard do wizard","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":4,"actualMs":241000,"epicId":"E-009","epicTitle":"General","tags":["setup","onboarding","teams","concurrency","wizard"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T05:42:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-003","title":"Selecção por defeito PSE — última da semana ou hoje","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":45,"actualMinutes":49,"actualMs":2944000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","ui","default-selection","today"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:17:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-005","title":"Tab exercícios planeamento — ícone clipboard typography","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":50,"actualMinutes":63,"actualMs":3788000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","ui","icon","exercicios"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:05:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-010","title":"Ícones PSE e Wellness na sidebar e no sumário da sessão","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":360,"actualMinutes":359,"actualMs":21595000,"epicId":"E-009","epicTitle":"General","tags":["ui","icons","pse","wellness","navigation","planning"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:05:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-006","title":"Auto-gerar nome ao criar PSE no planeamento (treino/jogo)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","planeamento","naming","auto-generate"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T16:32:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-007","title":"Auto-gerar nome ao criar Wellness no planeamento (treino/jogo)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","planeamento","naming","auto-generate"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T16:32:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-006","title":"Fotos dos jogadores não aparecem no PSE e Wellness (proxy frontend em vez de S3)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":131000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","avatar","jogadores","s3","proxy","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T15:39:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-012","title":"Timeline de envio — evento quando PSE/Wellness é respondido ou modificado","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":27,"actualMs":1677000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","email","smtp","timeline","audit"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T15:39:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-003","title":"Timeline de eventos no estado de envio de emails de notificação","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":482,"actualMs":28961000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","ui","email","notifications"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:15:03Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-004","title":"Timeline de eventos no estado de envio de emails de notificação","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":484,"actualMs":29051000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","ui","email","notifications"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:15:03Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-011","title":"Ordenação SMTP — timestamp, prioridade lifecycle, depois reiceivedAt","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":120,"actualMinutes":2,"actualMs":127000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","email","smtp","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:05:32Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-007","title":"Spam de emails PSE — cron reenvia sem onlyUnnotified e wipe de notifiedAt","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":156000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","bug","email","notifications","sendgrid","cron"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T09:46:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-005","title":"Spam de emails Wellness — cron reenvia apesar de estado Processado","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":75,"actualMinutes":75,"actualMs":4519000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","bug","email","notifications","sendgrid","cron","critical","smtp","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T09:30:01Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-001","title":"PSE salta para a primeira da semana após editar duração","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":20,"actualMinutes":19,"actualMs":1161000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","bug","navigation","session-duration"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T07:41:43Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"workItemsByEpic":{"E-009":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-009","epicTitle":"General","rows":[{"kind":"task","id":"T-055","title":"Open Graph — usar og.png como imagem Facebook no site e na app","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"epicId":"E-009","epicTitle":"General","tags":["seo","opengraph","facebook","metadata","website","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-056","title":"Google Analytics — gtag na app e no site","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"epicId":"E-009","epicTitle":"General","tags":["analytics","google-analytics","gtag","website","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-028","title":"Setup/wizard — país não pré-preenche ao escolher equipa do datacenter","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"epicId":"E-009","epicTitle":"General","tags":["bug","setup","onboarding","wizard","country-picker","datacenter"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:27:50Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-030","title":"Modal Completa o teu perfil aparece no setup/onboarding wizard","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["perfil","setup","onboarding","dialog","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:08:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-066","title":"Script CLI para copiar equipa entre organizações","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2358000,"epicId":"E-009","epicTitle":"General","tags":["ops","mongo","script","team","migration"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T16:08:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-017","title":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","status":"done","priority":"critical","size":"XL","points":24,"estimateMinutes":1390,"actualMinutes":1028,"actualMs":61734000,"epicId":"E-009","epicTitle":"General","tags":["organizacoes","auth0","migracao","setup-wizard","sidebar","401","404","multi-tenant"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","workItemCount":8,"doneWorkItemCount":8,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-020","title":"Picker de países — lista filtrada ao reabrir e bandeiras","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["ui","forms","countries","combobox","setup","onboarding","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-021","title":"Picker de países no modal de facturação — clique não selecciona","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-009","epicTitle":"General","tags":["ui","forms","countries","combobox","dialog","billing","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-014","title":"Frontend build falha (zodResolver SeasonSettings) e avisos ESLint","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"epicId":"E-009","epicTitle":"General","tags":["frontend","build","eslint","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:54:42Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-008","title":"Equipas duplicadas no setup/onboarding — retry e guard do wizard","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":4,"actualMs":241000,"epicId":"E-009","epicTitle":"General","tags":["setup","onboarding","teams","concurrency","wizard"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T05:42:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-010","title":"Ícones PSE e Wellness na sidebar e no sumário da sessão","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":360,"actualMinutes":359,"actualMs":21595000,"epicId":"E-009","epicTitle":"General","tags":["ui","icons","pse","wellness","navigation","planning"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:05:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-006","title":"Fotos dos jogadores não aparecem no PSE e Wellness (proxy frontend em vez de S3)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":131000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","avatar","jogadores","s3","proxy","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T15:39:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-012","title":"Timeline de envio — evento quando PSE/Wellness é respondido ou modificado","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":27,"actualMs":1677000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","email","smtp","timeline","audit"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T15:39:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-011","title":"Ordenação SMTP — timestamp, prioridade lifecycle, depois reiceivedAt","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":120,"actualMinutes":2,"actualMs":127000,"epicId":"E-009","epicTitle":"General","tags":["pse","wellness","email","smtp","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:05:32Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-001":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-001","epicTitle":"Motor de exercícios","rows":[{"kind":"task","id":"T-052","title":"Contador de caracteres na descrição e materiais do exercício (aviso soft)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":60000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["ui","motor-exercicios","editor","description","materials","character-limit"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:05:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-051","title":"Melhorias UI — badge Novo no marketplace, paginação no footer e labels lineup","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["ui","motor-exercicios","marketplace","pagination","lineup","i18n","microciclo","planeamento"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:04:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-027","title":"Editor — copy/paste de seta/curva perde pontos de controlo da curvatura","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["bug","motor-exercicios","editor","copy-paste","arrow","curve"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:27:50Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-016","title":"Editor — copy/paste não funciona com múltiplos elementos seleccionados","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","editor","copy-paste","multi-select","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-05T00:07:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-005","title":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":11,"actualMs":685000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","planeamento","categoria","fase-tipo","multi-select"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-05T00:00:08Z","workItemCount":1,"doneWorkItemCount":1,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-006","title":"Duplicar exercício com confirmação e sufixo (copia)","status":"done","priority":"medium","size":"M","points":4,"estimateMinutes":20,"actualMinutes":18,"actualMs":1127000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","duplicate","modal"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-05T00:00:08Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-026","title":"/pub/media/*.woff2 404 ao exportar/renderizar exercícios","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":620000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","fonts","pub","media-render"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T23:59:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-001","title":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","status":"done","priority":"medium","size":"M","points":5,"estimateMinutes":570,"actualMinutes":561,"actualMs":33710000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","ui","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-04T23:59:54Z","workItemCount":3,"doneWorkItemCount":3,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-048","title":"Guardar exercício — media em background (imagem primeiro, depois vídeo e claro)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","media","preview","performance","api","background"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T23:55:40Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-047","title":"Lista vertical — thumbnail a 100% do cartão sem cortes","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2344000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","layout","thumbnail","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T17:35:36Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-046","title":"Lista horizontal — thumbnail a preencher a coluna sem espaços em branco","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":15,"actualMinutes":13,"actualMs":780000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","layout","thumbnail","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T16:55:31Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-030","title":"Lista de exercícios — sem pasta primeiro, pastas por baixo","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":0,"actualMs":16000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","folders","ux","ordering"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T16:16:35Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-029","title":"Lista de exercícios paginada (pastas lazy + pesquisa plana)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":7,"actualMs":475000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","list","pagination","folders","performance","search"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T15:18:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-022","title":"Exercise editor — PageHeader maximum update depth exceeded","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":295000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","editor","page-header","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:16:55Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-012","title":"Bola teleporta ao associar a jogador durante animação","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":187000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","animacao","bola","attachment","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T11:14:09Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-011","title":"Texto no vídeo do exercício usa fonte diferente do portal","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","video","font","export","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-29T10:38:42Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-022","title":"Suavizar profundidade do layout de campo 3D","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":0,"epicId":"E-001","epicTitle":"Motor de exercícios","tags":["motor-exercicios","field","perspective","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T09:37:11Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-002":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-002","epicTitle":"PSE","rows":[{"kind":"bug","id":"B-036","title":"PSE — skeleton em loop numa semana sem treinos","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":78,"actualMinutes":1,"actualMs":88000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","rpe","loading","empty-state"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T16:20:40Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-003","title":"Selecção por defeito PSE — última da semana ou hoje","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":45,"actualMinutes":49,"actualMs":2944000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","ui","default-selection","today"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:17:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-006","title":"Auto-gerar nome ao criar PSE no planeamento (treino/jogo)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","planeamento","naming","auto-generate"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T16:32:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-003","title":"Timeline de eventos no estado de envio de emails de notificação","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":482,"actualMs":28961000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","ui","email","notifications"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:15:03Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-007","title":"Spam de emails PSE — cron reenvia sem onlyUnnotified e wipe de notifiedAt","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":156000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","bug","email","notifications","sendgrid","cron"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T09:46:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-001","title":"PSE salta para a primeira da semana após editar duração","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":20,"actualMinutes":19,"actualMs":1161000,"epicId":"E-002","epicTitle":"PSE","tags":["pse","bug","navigation","session-duration"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T07:41:43Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-003":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-003","epicTitle":"Wellness","rows":[{"kind":"bug","id":"B-010","title":"Wellness manual no planeamento exige treino/jogo","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":56000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","planeamento","i18n","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T09:00:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-007","title":"Auto-gerar nome ao criar Wellness no planeamento (treino/jogo)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","planeamento","naming","auto-generate"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T16:32:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-004","title":"Timeline de eventos no estado de envio de emails de notificação","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":484,"actualMs":29051000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","ui","email","notifications"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T10:15:03Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-005","title":"Spam de emails Wellness — cron reenvia apesar de estado Processado","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":75,"actualMinutes":75,"actualMs":4519000,"epicId":"E-003","epicTitle":"Wellness","tags":["wellness","bug","email","notifications","sendgrid","cron","critical","smtp","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T09:30:01Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-004":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-004","epicTitle":"Planeamento","rows":[{"kind":"story","id":"S-007","title":"Exportar calendário do planeamento em PDF (mensal e semana)","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":22,"actualMs":1339000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","pdf","export","calendar","preview"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"","workItemCount":1,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-053","title":"Intensidade do treino — níveis 1–10 e slider no formulário","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","treino","intensidade","slider","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:06:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-050","title":"Código sequencial UT/TS nos treinos da época/equipa","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":9,"actualMs":542000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","treino","codigo","i18n","reporte-treino"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:01:25Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-024","title":"Planeamento — MD-x em falta quando jogos estão a 7 dias","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":252000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","match-day","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:45:12Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-023","title":"Planeamento — tipo de jogo amigável não é gravado","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","jogo","match-type","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T12:26:10Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-011","title":"Mostrar meso e micro ciclos no calendário de planeamento","status":"done","priority":"high","size":"XL","points":8,"estimateMinutes":80,"actualMinutes":317,"actualMs":19076000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","calendar","periodizacao","meso-ciclo","micro-ciclo","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:47:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-013","title":"Campo livre aparece em branco no relatório de unidade de treino","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":206000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","training-report","exercises","field-preset","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T16:05:20Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-020","title":"Expanded layout — botão Voltar com hit target decente","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":66000,"epicId":"E-004","epicTitle":"Planeamento","tags":["ui","ux","expanded-layout","planeamento"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T07:09:36Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-009","title":"Export PDF semana omite jogos no domingo (filtro to date-only)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":70000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","pdf","export","games","api"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T08:28:54Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-002","title":"Sheet criar jogo no planeamento mostra i18n em inglês","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":10,"actualMinutes":1,"actualMs":60000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","i18n","bug","sheet","jogo"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-27T07:53:18Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-004","title":"Reporte treino — text-gray-400 para text-gray-600","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":180000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","ui","reporte-treino","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-27T07:53:18Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-005","title":"Tab exercícios planeamento — ícone clipboard typography","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":50,"actualMinutes":63,"actualMs":3788000,"epicId":"E-004","epicTitle":"Planeamento","tags":["planeamento","ui","icon","exercicios"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-23T17:05:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-005":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-005","epicTitle":"Lineup","rows":[{"kind":"task","id":"T-054","title":"Jogador — campos Número e Pé preferencial (lista e export lineup)","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"epicId":"E-005","epicTitle":"Lineup","tags":["lineup","jogador","plantel","export","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-12T00:07:29Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-027","title":"Exportar plantel — documento estilo relatório de unidade de treino","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"epicId":"E-005","epicTitle":"Lineup","tags":["lineup","plantel","export","pdf","report","print"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-05T00:17:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-006":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-006","epicTitle":"Website","rows":[{"kind":"task","id":"T-057","title":"Melhorar SEO do website e da app (titles, OG, robots, schema)","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":41,"actualMs":2482000,"epicId":"E-006","epicTitle":"Website","tags":["seo","metadata","opengraph","website","frontend","robots","accessibility"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:50:53Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-021","title":"Hero — embed Loom com moldura responsiva","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":54000,"epicId":"E-006","epicTitle":"Website","tags":["website","hero"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-28","completedAt":"2026-07-28T08:32:22Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-004","title":"Artigos em destaque — imagem sem cover inflaciona os cartões","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":69000,"epicId":"E-006","epicTitle":"Website","tags":["website","blog","featured","images","cover","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-008","title":"Artigos website — restaurar bullets de listagem (disc)","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"epicId":"E-006","epicTitle":"Website","tags":["website","artigos","css","lists","typography"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-009","title":"Artigos website — imagens a 100% da largura do conteúdo","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"epicId":"E-006","epicTitle":"Website","tags":["website","artigos","images","css"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:56:39Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-007":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-007","epicTitle":"Admin dashboard","rows":[{"kind":"bug","id":"B-034","title":"Resposta admin fecha ticket em vez de passar a Em progresso","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":204000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","support","tickets"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T11:15:47Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-009","title":"Gerir autores de blog posts no admin (incluindo autores manuais)","status":"done","priority":"medium","size":"XL","points":12,"estimateMinutes":705,"actualMinutes":706,"actualMs":42366000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","website","blog","autores"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-08-10T05:54:44.000Z","workItemCount":5,"doneWorkItemCount":5,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-008","title":"CRUD de tags e categorias dos artigos do website no admin","status":"done","priority":"medium","size":"L","points":5,"estimateMinutes":25,"actualMinutes":480,"actualMs":28800000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","website","tags","categorias","artigos","crud"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-29T07:41:30Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-010","title":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","status":"done","priority":"high","size":"XL","points":20,"estimateMinutes":580,"actualMinutes":572,"actualMs":34321000,"epicId":"E-007","epicTitle":"Admin dashboard","tags":["admin","users","teams","tabs","dashboard"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T07:54:31Z","workItemCount":9,"doneWorkItemCount":9,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-008":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-008","epicTitle":"Perfil de Utilizadores e Equipas","rows":[{"kind":"bug","id":"B-025","title":"Utilizadores duplicados na lista admin (mesmo auth0Sub)","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":60,"actualMinutes":59,"actualMs":3597000,"epicId":"E-008","epicTitle":"Perfil de Utilizadores e Equipas","tags":["perfil","admin","utilizadores","auth0","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:57:14Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"bug","id":"B-003","title":"Avatar no perfil não sincroniza no Auth0 (usar proxy frontend em vez de S3)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":1,"actualMs":70000,"epicId":"E-008","epicTitle":"Perfil de Utilizadores e Equipas","tags":["perfil","avatar","auth0","s3","proxy","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:44:32Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-010":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-010","epicTitle":"Pagamentos","rows":[{"kind":"story","id":"S-012","title":"Página de definições de facturação por conta (formulário + sync Stripe)","status":"done","priority":"high","size":"XL","points":27,"estimateMinutes":4320,"actualMinutes":4320,"actualMs":259200000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","settings","billing"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":9,"doneWorkItemCount":9,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-013","title":"Dialog CTA quando subscrição activa sem dados de facturação","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":502,"actualMinutes":482,"actualMs":28969000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","ux","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-014","title":"Listagem de facturas Stripe na página de facturação","status":"done","priority":"medium","size":"S","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"epicId":"E-010","epicTitle":"Pagamentos","tags":["pagamentos","facturacao","stripe","invoices"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-03T15:57:46Z","workItemCount":1,"doneWorkItemCount":1,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-011":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-011","epicTitle":"Backup do produto","rows":[{"kind":"story","id":"S-015","title":"Backup automático diário Mongo → S3 (02:00)","status":"done","priority":"high","size":"L","points":10,"estimateMinutes":515,"actualMinutes":482,"actualMs":28952000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","backup","mongo","s3","cron"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-11T16:08:09Z","workItemCount":3,"doneWorkItemCount":3,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"task","id":"T-064","title":"Script para apagar wellness/RPE legacy do Mongo","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":50,"actualMinutes":2,"actualMs":153000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","mongo","cleanup","wellness","rpe","backup"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-10T23:47:21Z","workItemCount":0,"doneWorkItemCount":0,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-016","title":"CLI NPM para backup manual com inquirer","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":20,"actualMinutes":1,"actualMs":87000,"epicId":"E-011","epicTitle":"Backup do produto","tags":["ops","backup","cli","inquirer","npm"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-03","completedAt":"2026-08-03T15:44:22Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-012":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","rows":[{"kind":"story","id":"S-018","title":"Nova UI de login (shadcn login-02) com Auth0","status":"done","priority":"high","size":"XL","points":21,"estimateMinutes":625,"actualMinutes":32,"actualMs":1957934,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","login","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:12:30Z","workItemCount":10,"doneWorkItemCount":8,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-020","title":"Fluxo de convite para organização (email, registo, login e confirmação)","status":"done","priority":"critical","size":"XL","points":35,"estimateMinutes":1225,"actualMinutes":86,"actualMs":5219401,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","convites","sendgrid","organizacoes","signup","login"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T15:22:58Z","workItemCount":14,"doneWorkItemCount":7,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"kind":"story","id":"S-019","title":"Nova UI de registo normal (shadcn signup-02) com Auth0","status":"done","priority":"high","size":"L","points":8,"estimateMinutes":310,"actualMinutes":2,"actualMs":120000,"epicId":"E-012","epicTitle":"Auth UI — login, registo e convites de organização","tags":["auth","signup","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","workItemCount":2,"doneWorkItemCount":2,"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]}},"itemsByStory":{"E-009::S-017":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-009","storyId":"S-017","storyTitle":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","items":[{"id":"B-031","type":"bug","title":"Conta organizacional nova não fica em Trial (app)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["organizacoes","trial","subscriptions","admin","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-031-org-nova-sem-trial-app.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-032","type":"bug","title":"Página de facturação em org abre Auth0 consent em vez da UI","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","billing","auth0","cookie","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-032-facturacao-org-auth0-consent.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-037","type":"bug","title":"Wizard — passo pessoal/org falta no registo e aparece ao criar equipa","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":173000,"tags":["setup-wizard","onboarding","organizacoes","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:24:00Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-037-wizard-passo-pessoal-org-registo-vs-nova-equipa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-058","type":"task","title":"Entidade Organização, membership e API (sair das Auth0 Orgs)","status":"done","priority":"critical","size":"L","points":5,"estimateMinutes":110,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","auth0","api","membership","multi-tenant"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-058-entidade-organizacao-membership-api.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-059","type":"task","title":"Script de migração Auth0 Organizations → sistema próprio","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":65,"actualMinutes":66,"actualMs":3961000,"tags":["organizacoes","auth0","migracao","script"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-059-script-migracao-auth0-orgs.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-060","type":"task","title":"Selector de organização na sidebar (canto inferior esquerdo)","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","sidebar","selector","frontend","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-060-selector-organizacao-sidebar.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-061","type":"task","title":"Setup wizard — conta pessoal vs organizacional no 1º passo","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["setup-wizard","onboarding","organizacoes","ux","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-061-setup-wizard-pessoal-vs-organizacional.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-062","type":"task","title":"Páginas 404 (botão início) e 401 (redirect login)","status":"done","priority":"critical","size":"S","points":2,"estimateMinutes":45,"actualMinutes":0,"actualMs":0,"tags":["404","401","frontend","auth","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T15:50:52Z","parent":"S-017","epic":"E-009","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-062-paginas-404-e-401.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-001::S-005":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-001","storyId":"S-005","storyTitle":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","items":[{"id":"T-032","type":"task","title":"Categorias exercícios/treinos — remover Esquemas tácticos e renomear labels","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":8,"actualMs":480000,"tags":["motor-exercicios","planeamento","categoria","i18n","labels"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T23:59:54Z","parent":"S-005","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/items/T-032-categorias-renomear-remover-esquemas.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-001::S-006":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-001","storyId":"S-006","storyTitle":"Duplicar exercício com confirmação e sufixo (copia)","items":[{"id":"B-015","type":"bug","title":"Duplicar exercício não regenera imagens/vídeos de preview","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":15,"actualMinutes":13,"actualMs":780000,"tags":["motor-exercicios","duplicate","media","preview","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T23:59:54Z","parent":"S-006","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-049","type":"task","title":"Spinner de loading no botão duplicar exercício","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":5,"actualMs":347000,"tags":["motor-exercicios","duplicate","modal","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-04","completedAt":"2026-08-04T23:59:54Z","parent":"S-006","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/T-049-spinner-loading-duplicar-exercicio.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-001::S-001":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-001","storyId":"S-001","storyTitle":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","items":[{"id":"T-001","type":"task","title":"Aumentar tamanho do elemento de texto para 180%","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":46000,"tags":["motor-exercicios","ui","typography","text-element"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:36:26Z","parent":"S-001","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-001-texto-elemento-180.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-002","type":"task","title":"Aumentar tamanho das etiquetas inferiores para 180%","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":46000,"tags":["motor-exercicios","ui","typography","bottom-label"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-23","completedAt":"2026-07-28T07:36:26Z","parent":"S-001","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-002-etiqueta-inferior-180.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-028","type":"task","title":"Redimensionar tamanho do elemento de texto com slider","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":560,"actualMinutes":560,"actualMs":33618000,"tags":["motor-exercicios","ui","typography","text","slider"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-04T19:00:27Z","parent":"S-001","epic":"E-001","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-028-redimensionar-texto-slider.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-002::S-003":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-002","storyId":"S-003","storyTitle":"Timeline de eventos no estado de envio de emails de notificação","items":[],"errors":[]},"E-003::S-004":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-003","storyId":"S-004","storyTitle":"Timeline de eventos no estado de envio de emails de notificação","items":[],"errors":[]},"E-004::S-007":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-004","storyId":"S-007","storyTitle":"Exportar calendário do planeamento em PDF (mensal e semana)","items":[{"id":"B-029","type":"bug","title":"Export semana — cabeçalhos desformatados quando MD-X só até meio da semana","status":"backlog","priority":"medium","size":"S","points":2,"estimateMinutes":55,"actualMinutes":0,"actualMs":0,"tags":["bug","planeamento","export","pdf","semana","md-x","layout"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-10","completedAt":"","parent":"S-007","epic":"E-004","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/items/B-029-export-semana-cabecalhos-desformatados-md-x.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-004::S-011":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-004","storyId":"S-011","storyTitle":"Mostrar meso e micro ciclos no calendário de planeamento","items":[],"errors":[]},"E-007::S-009":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-007","storyId":"S-009","storyTitle":"Gerir autores de blog posts no admin (incluindo autores manuais)","items":[{"id":"T-023","type":"task","title":"Port manual article author CRUD API to worktree-1","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":190000,"tags":["admin","website","blog","autores","api"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T06:53:55Z","parent":"S-009","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-023-port-author-crud-worktree-1-api.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-024","type":"task","title":"Admin sidebar submenu for article authors","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":55,"actualMinutes":55,"actualMs":3344000,"tags":["admin","website","blog","autores","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T10:38:42Z","parent":"S-009","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-024-admin-sidebar-article-authors.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-025","type":"task","title":"Author photo file upload to S3","status":"done","priority":"medium","size":"L","points":5,"estimateMinutes":110,"actualMinutes":111,"actualMs":6688000,"tags":["admin","website","blog","autores","s3"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T10:38:42Z","parent":"S-009","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-025-author-photo-s3-upload.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-026","type":"task","title":"Authors table UI parity + text search","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":55,"actualMinutes":55,"actualMs":3344000,"tags":["admin","website","blog","autores","frontend"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-29","completedAt":"2026-07-29T10:38:42Z","parent":"S-009","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-026-authors-table-ui-search.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-031","type":"task","title":"Editar descrição do autor do blog (manual e utilizador) e mostrar no site","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["admin","website","blog","autores","description"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-30","completedAt":"2026-08-10T05:54:44.000Z","parent":"S-009","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-031-editar-descricao-autor-blog.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-007::S-008":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-007","storyId":"S-008","storyTitle":"CRUD de tags e categorias dos artigos do website no admin","items":[],"errors":[]},"E-007::S-010":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-007","storyId":"S-010","storyTitle":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","items":[{"id":"T-013","type":"task","title":"Tabs Utilizadores / Equipas em /admin/users","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":9,"actualMs":540000,"tags":["admin","users","teams","tabs","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T06:30:00Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-013-tabs-utilizadores-equipas-admin-users.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-014","type":"task","title":"Listagem de utilizadores com Criado em e Último acesso","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":14,"actualMs":840000,"tags":["admin","users","table","api"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T06:35:00Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-014-listagem-utilizadores-criado-ultimo-acesso.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-015","type":"task","title":"Coluna total de equipas com dialog de detalhe","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":600000,"tags":["admin","users","teams","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T06:31:00Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-015-coluna-equipas-dialog.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-016","type":"task","title":"Coluna contas com acesso e dialog de subscrição","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":14,"actualMs":840000,"tags":["admin","users","accounts","subscription","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T06:35:00Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-016-coluna-contas-dialog-subscricao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-017","type":"task","title":"Estado do utilizador calculado a partir das contas","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":600000,"tags":["admin","users","status","subscription"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-27","completedAt":"2026-07-27T06:31:00Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-017-estado-utilizador-derivado-contas.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-018","type":"task","title":"Acções nos dialogs de equipas e contas do utilizador","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":25,"actualMinutes":21,"actualMs":1313000,"tags":["admin","users","teams","accounts","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-07-27","completedAt":"2026-07-27T07:52:10Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-018-accoes-dialogs-equipas-contas.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-019","type":"task","title":"Coluna de métricas agregadas na lista de utilizadores","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":605000,"tags":["admin","users","metrics"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-07-27","completedAt":"2026-07-27T07:52:10Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-019-metricas-agregadas-utilizadores.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-033","type":"task","title":"Modal subscrição admin — botão ver cliente no Stripe","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["admin","stripe","subscription","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-033-modal-subscricao-botao-cliente-stripe.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-041","type":"task","title":"Lista equipas admin — país sob o nome em vez do desporto","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":3,"actualMs":183000,"tags":["admin","teams","ui","copy"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-07-31T16:55:45Z","parent":"S-010","epic":"E-007","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-010::S-012":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-010","storyId":"S-012","storyTitle":"Página de definições de facturação por conta (formulário + sync Stripe)","items":[{"id":"B-017","type":"bug","title":"Formulário de facturação — botão Guardar fica sempre desabilitado","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","rhf","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-017-formulario-facturacao-botao-guardar-desabilitado.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-018","type":"bug","title":"Facturação — nome da empresa vs nome da conta no sync Stripe","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","stripe","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-033","type":"bug","title":"Modal facturação — inputs Empresa mostram erro antes do submit","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","rhf","bug","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-10","completedAt":"2026-08-11T16:08:09Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-033-modal-facturacao-erros-antes-submit.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-035","type":"task","title":"Formulário facturação — toggle particular/empresa com campos condicionais","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-035-formulario-toggle-particular-empresa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-036","type":"task","title":"Facturação — campos opcionais para particular, obrigatórios para empresa","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","validation"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-036-campos-opcionais-particular-obrigatorios-empresa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-037","type":"task","title":"Checkout — recolher dados de facturação antes do Stripe","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","checkout","stripe","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-037-checkout-requer-formulario-facturacao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-038","type":"task","title":"Pré-seleccionar país de facturação com o país da equipa","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-038-preseleccionar-pais-facturacao-da-equipa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-039","type":"task","title":"Modal dados de faturação — botão Cancelar","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","dialog","ux"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-039-modal-facturacao-botao-cancelar.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-040","type":"task","title":"Copy dos botões na página de facturação","status":"done","priority":"low","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","i18n","copy"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-012","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-040-copy-botoes-pagina-facturacao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-010::S-013":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-010","storyId":"S-013","storyTitle":"Dialog CTA quando subscrição activa sem dados de facturação","items":[{"id":"B-019","type":"bug","title":"Dialog de facturação aparece durante o setup da equipa","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","setup","onboarding","dialog","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-013","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-035","type":"bug","title":"Modal Completa faturação — botões colados sem margem","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":22,"actualMinutes":2,"actualMs":169000,"tags":["pagamentos","facturacao","ux","dialog"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T11:32:39Z","parent":"S-013","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-035-modal-completa-faturacao-botoes-colados.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-010::S-014":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-010","storyId":"S-014","storyTitle":"Listagem de facturas Stripe na página de facturação","items":[{"id":"T-034","type":"task","title":"Lista de facturas paginada (máx. 5 por página)","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","invoices","pagination"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-07-31","completedAt":"2026-08-03T15:57:14Z","parent":"S-014","epic":"E-010","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/items/T-034-lista-facturas-paginada-5-por-pagina.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-011::S-015":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-011","storyId":"S-015","storyTitle":"Backup automático diário Mongo → S3 (02:00)","items":[{"id":"T-042","type":"task","title":"Pipeline mongodump → ZIP → upload S3","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":25,"actualMinutes":1,"actualMs":108000,"tags":["ops","backup","mongo","s3"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:42:11Z","parent":"S-015","epic":"E-011","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-042-pipeline-mongodump-zip-upload-s3.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-043","type":"task","title":"Agendar backup diário às 02:00","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":44000,"tags":["ops","backup","cron","schedule"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:42:55Z","parent":"S-015","epic":"E-011","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-043-agendar-backup-diario-02h.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-063","type":"task","title":"Nome do ZIP de backup a partir de APP_BASE_URL","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["ops","backup","mongo","s3"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-11","completedAt":"2026-08-11T16:08:09Z","parent":"S-015","epic":"E-011","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-063-backup-filename-app-base-url.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-011::S-016":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-011","storyId":"S-016","storyTitle":"CLI NPM para backup manual com inquirer","items":[{"id":"T-044","type":"task","title":"CLI npm + inquirer (host, user, password)","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":1,"actualMs":65000,"tags":["ops","backup","cli","inquirer","npm"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:44:00Z","parent":"S-016","epic":"E-011","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-044-cli-npm-inquirer-backup-mongo.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-045","type":"task","title":"Documentar env vars e uso do backup","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":22000,"tags":["ops","backup","docs"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-03","completedAt":"2026-08-03T15:44:22Z","parent":"S-016","epic":"E-011","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-045-documentar-backup-env-uso.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-012::S-018":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-012","storyId":"S-018","storyTitle":"Nova UI de login (shadcn login-02) com Auth0","items":[{"id":"B-038","type":"bug","title":"Registo redirecciona para login Auth0 em vez do wizard","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":180000,"tags":["auth","signup","auth0","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:38:00Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-038-registo-redirect-auth0-login-em-vez-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-039","type":"bug","title":"Confirmação de logout nativa (sem página Auth0)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":120000,"tags":["auth","logout","ui","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:42:00Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-039-confirmacao-logout-nativa.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-040","type":"bug","title":"Nunca usar logout Auth0 (só sessão local)","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":82000,"tags":["auth","logout","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:45:29Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-040-nunca-usar-logout-auth0.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-067","type":"task","title":"Layout da página de login (shadcn login-02)","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","login","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-067-layout-pagina-login-shadcn-login-02.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-068","type":"task","title":"Ligar formulário de login ao Auth0","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","login","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-068-ligar-formulario-login-auth0.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-078","type":"task","title":"Recuperar password no login (Auth0 change_password)","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":199000,"tags":["auth","login","password","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:07:19Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-078-recuperar-password-no-login.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-079","type":"task","title":"Adaptar login e registo ao layout shadcn login-04","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":99000,"tags":["auth","login","signup","ui","shadcn"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:12:30Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-079-adaptar-login-registo-login-04.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-081","type":"task","title":"Login e registo — loading com spinner nos botões","status":"in_progress","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":12,"actualMs":757467,"tags":["auth","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-14","completedAt":"","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-081-login-signup-button-spinners.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-082","type":"task","title":"Logout — confirmação a página inteira sem cover","status":"in_progress","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":6,"actualMs":400467,"tags":["auth","logout","ui"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-14","completedAt":"","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-082-logout-sem-cover-imagem.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-083","type":"task","title":"Auth light — logo cid_azul nas páginas login/logout/registo","status":"done","priority":"low","size":"XS","points":1,"estimateMinutes":15,"actualMinutes":0,"actualMs":0,"tags":["auth","ui","branding"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-14","completedAt":"2026-08-14T14:38:31Z","parent":"S-018","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-083-auth-logo-light-cid-azul.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]},"E-012::S-020":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-012","storyId":"S-020","storyTitle":"Fluxo de convite para organização (email, registo, login e confirmação)","items":[{"id":"B-041","type":"bug","title":"Registo por convite falha com “conta já existe”","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":105000,"tags":["auth","convites","signup","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:54:16Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-041-registo-convite-conta-ja-existe.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-042","type":"bug","title":"Email de convite sem assunto","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":183000,"tags":["auth","convites","sendgrid","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T17:58:21Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-042-email-convite-sem-assunto.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-043","type":"bug","title":"Resend convite 404 na API main","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":87000,"tags":["auth","convites","api","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-14","completedAt":"2026-08-14T10:18:00Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-043-resend-convite-404-api-main.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-044","type":"bug","title":"Após registo por convite volta ao link inválido em vez do wizard","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":81000,"tags":["auth","convites","signup","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-14","completedAt":"2026-08-14T10:31:00Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-044-registo-convite-redirect-wizard.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-045","type":"bug","title":"Resend convite 500 com id fake accepted-auth0","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":33,"actualMs":2012467,"tags":["auth","convites","api","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-14","completedAt":"","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-045-resend-convite-accepted-fake-id-500.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"B-046","type":"bug","title":"Invite landing 500 ao setar cookie no RSC","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":21,"actualMs":1292467,"tags":["auth","convites","bug"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-14","completedAt":"","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-046-invite-landing-cookie-rsc-500.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-071","type":"task","title":"Template SendGrid de convite à organização","status":"done","priority":"critical","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":172000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T16:25:58Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-071-template-sendgrid-convite-organizacao.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-073","type":"task","title":"Rota landing de convite e resolução de estado","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-073-rota-landing-convite-resolver-estado.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-074","type":"task","title":"Registo por convite — email readonly + contexto da org","status":"done","priority":"critical","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-074-registo-por-convite-email-readonly.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-080","type":"task","title":"Registo por convite — password + confirmar password","status":"in_progress","priority":"medium","size":"S","points":2,"estimateMinutes":55,"actualMinutes":18,"actualMs":1106467,"tags":["auth","convites","signup"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"created":"2026-08-14","completedAt":"","parent":"S-020","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-080-registo-convite-password-confirmar.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[{"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-072-api-enviar-email-convite-create-resend.md","projectId":"/Users/menda0/Projects/coachid/new/coachid-taskmark","projectName":"coachid-taskmark","storyId":"S-020","message":"Nested mappings are not allowed in compact mappings at line 3, column 8:\n\ntitle: API: enviar email no create/resend de convite\n ^\n"},{"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-075-convite-utilizador-existente-login-confirmacao.md","projectId":"/Users/menda0/Projects/coachid/new/coachid-taskmark","projectName":"coachid-taskmark","storyId":"S-020","message":"Nested mappings are not allowed in compact mappings at line 3, column 8:\n\ntitle: Convite: utilizador existente — login e página de confirmação\n ^\n"},{"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-076-convite-ja-logado-pagina-confirmacao.md","projectId":"/Users/menda0/Projects/coachid/new/coachid-taskmark","projectName":"coachid-taskmark","storyId":"S-020","message":"Nested mappings are not allowed in compact mappings at line 3, column 8:\n\ntitle: Convite: já logado e email corresponde — só confirmação\n ^\n"},{"filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-077-convite-utilizador-errado-pagina-erro.md","projectId":"/Users/menda0/Projects/coachid/new/coachid-taskmark","projectName":"coachid-taskmark","storyId":"S-020","message":"Nested mappings are not allowed in compact mappings at line 3, column 8:\n\ntitle: Convite: utilizador logado errado — página de erro\n ^\n"}]},"E-012::S-019":{"project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"},"epicId":"E-012","storyId":"S-019","storyTitle":"Nova UI de registo normal (shadcn signup-02) com Auth0","items":[{"id":"T-069","type":"task","title":"Layout da página de registo normal (shadcn signup-02)","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","signup","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-019","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-069-layout-pagina-registo-shadcn-signup-02.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}},{"id":"T-070","type":"task","title":"Ligar formulário de registo normal ao Auth0","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","signup","ui","shadcn","auth0"],"reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"created":"2026-08-12","completedAt":"2026-08-12T14:53:58Z","parent":"S-019","epic":"E-012","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-070-ligar-formulario-registo-auth0.md","project":{"id":"/Users/menda0/Projects/coachid/new/coachid-taskmark","name":"coachid-taskmark","projectPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark","boardPath":"/Users/menda0/Projects/coachid/new/coachid-taskmark"}}],"errors":[]}},"statusMetrics":{"totalWorkItems":143,"completeWorkItems":136,"currentWeekPointsDone":111,"currentSpeedPtsPerWeek":53,"speedWeekCount":3,"contributors":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}]},"countableCompletions":[{"completedAt":"2026-08-11T15:50:52Z","points":3},{"completedAt":"2026-08-11T15:50:52Z","points":3},{"completedAt":"2026-08-12T17:24:00Z","points":2},{"completedAt":"2026-08-11T15:50:52Z","points":5},{"completedAt":"2026-08-11T15:50:52Z","points":3},{"completedAt":"2026-08-11T15:50:52Z","points":3},{"completedAt":"2026-08-11T15:50:52Z","points":3},{"completedAt":"2026-08-11T15:50:52Z","points":2},{"completedAt":"2026-07-23T15:39:54Z","points":3},{"completedAt":"2026-07-27T05:42:30Z","points":1},{"completedAt":"2026-07-29T16:54:42Z","points":2},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-11T16:27:50Z","points":2},{"completedAt":"2026-08-11T16:08:09Z","points":3},{"completedAt":"2026-07-23T17:05:30Z","points":3},{"completedAt":"2026-07-23T10:05:32Z","points":2},{"completedAt":"2026-07-23T15:39:54Z","points":1},{"completedAt":"2026-08-11T16:50:53Z","points":2},{"completedAt":"2026-08-11T16:50:53Z","points":2},{"completedAt":"2026-08-11T16:08:09Z","points":1},{"completedAt":"2026-07-28T07:36:26Z","points":1},{"completedAt":"2026-07-28T07:36:26Z","points":1},{"completedAt":"2026-08-04T19:00:27Z","points":3},{"completedAt":"2026-08-04T23:59:54Z","points":2},{"completedAt":"2026-08-04T23:59:54Z","points":2},{"completedAt":"2026-08-04T23:59:54Z","points":2},{"completedAt":"2026-07-29T10:38:42Z","points":3},{"completedAt":"2026-07-29T11:14:09Z","points":2},{"completedAt":"2026-08-05T00:07:39Z","points":3},{"completedAt":"2026-08-03T12:16:55Z","points":2},{"completedAt":"2026-08-04T23:59:54Z","points":2},{"completedAt":"2026-08-11T16:27:50Z","points":2},{"completedAt":"2026-07-28T09:37:11Z","points":2},{"completedAt":"2026-08-04T15:18:09Z","points":2},{"completedAt":"2026-08-04T16:16:35Z","points":1},{"completedAt":"2026-08-04T16:55:31Z","points":2},{"completedAt":"2026-08-04T17:35:36Z","points":1},{"completedAt":"2026-08-04T23:55:40Z","points":2},{"completedAt":"2026-08-12T00:04:29Z","points":3},{"completedAt":"2026-08-12T00:05:29Z","points":2},{"completedAt":"2026-07-23T07:41:43Z","points":1},{"completedAt":"2026-07-23T09:46:21Z","points":3},{"completedAt":"2026-08-11T16:20:40Z","points":2},{"completedAt":"2026-07-23T17:17:30Z","points":1},{"completedAt":"2026-07-23T16:32:53Z","points":2},{"completedAt":"2026-07-23T09:30:01Z","points":1},{"completedAt":"2026-07-28T09:00:21Z","points":2},{"completedAt":"2026-07-23T16:32:53Z","points":2},{"completedAt":"2026-07-27T07:53:18Z","points":1},{"completedAt":"2026-07-27T08:28:54Z","points":2},{"completedAt":"2026-07-29T16:05:20Z","points":2},{"completedAt":"2026-08-03T12:26:10Z","points":2},{"completedAt":"2026-08-03T12:45:12Z","points":2},{"completedAt":"2026-07-27T07:53:18Z","points":2},{"completedAt":"2026-07-23T17:05:30Z","points":1},{"completedAt":"2026-07-28T07:09:36Z","points":2},{"completedAt":"2026-08-12T00:01:25Z","points":2},{"completedAt":"2026-08-12T00:06:29Z","points":3},{"completedAt":"2026-08-05T00:17:14Z","points":2},{"completedAt":"2026-08-12T00:07:29Z","points":3},{"completedAt":"2026-07-28T07:56:39Z","points":2},{"completedAt":"2026-07-28T07:56:39Z","points":1},{"completedAt":"2026-07-28T07:56:39Z","points":1},{"completedAt":"2026-07-28T08:32:22Z","points":2},{"completedAt":"2026-08-11T16:50:53Z","points":1},{"completedAt":"2026-07-29T06:53:55Z","points":2},{"completedAt":"2026-07-29T10:38:42Z","points":1},{"completedAt":"2026-07-29T10:38:42Z","points":5},{"completedAt":"2026-07-29T10:38:42Z","points":1},{"completedAt":"2026-08-10T05:54:44.000Z","points":3},{"completedAt":"2026-07-27T06:30:00Z","points":2},{"completedAt":"2026-07-27T06:35:00Z","points":3},{"completedAt":"2026-07-27T06:31:00Z","points":2},{"completedAt":"2026-07-27T06:35:00Z","points":3},{"completedAt":"2026-07-27T06:31:00Z","points":2},{"completedAt":"2026-07-27T07:52:10Z","points":2},{"completedAt":"2026-07-27T07:52:10Z","points":2},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-07-31T16:55:45Z","points":1},{"completedAt":"2026-08-11T11:15:47Z","points":2},{"completedAt":"2026-07-28T07:44:32Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":1},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-11T16:08:09Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-11T11:32:39Z","points":1},{"completedAt":"2026-08-03T15:57:14Z","points":3},{"completedAt":"2026-08-03T15:42:11Z","points":5},{"completedAt":"2026-08-03T15:42:55Z","points":2},{"completedAt":"2026-08-11T16:08:09Z","points":3},{"completedAt":"2026-08-03T15:44:00Z","points":3},{"completedAt":"2026-08-03T15:44:22Z","points":1},{"completedAt":"2026-08-10T23:47:21Z","points":2},{"completedAt":"2026-08-12T17:38:00Z","points":2},{"completedAt":"2026-08-12T17:42:00Z","points":2},{"completedAt":"2026-08-12T17:45:29Z","points":2},{"completedAt":"2026-08-12T14:53:58Z","points":5},{"completedAt":"2026-08-12T14:53:58Z","points":3},{"completedAt":"2026-08-12T17:07:19Z","points":2},{"completedAt":"2026-08-12T17:12:30Z","points":2},{"completedAt":"2026-08-14T14:38:31Z","points":1},{"completedAt":"2026-08-12T14:53:58Z","points":5},{"completedAt":"2026-08-12T14:53:58Z","points":3},{"completedAt":"2026-08-12T17:54:16Z","points":2},{"completedAt":"2026-08-12T17:58:21Z","points":2},{"completedAt":"2026-08-14T10:18:00Z","points":2},{"completedAt":"2026-08-14T10:31:00Z","points":2},{"completedAt":"2026-08-12T16:25:58Z","points":2},{"completedAt":"2026-08-12T14:53:58Z","points":3},{"completedAt":"2026-08-12T14:53:58Z","points":5}],"hideCompletedDefaults":{"epics":false,"stories":false,"tasks":false,"overallWorkItems":false,"workItems":false},"detailsByPath":{"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/epic.md":{"id":"E-001","title":"Motor de exercícios","type":"epic","status":"in_progress","priority":"medium","size":"—","points":40,"estimateMinutes":1555,"actualMinutes":1154,"actualMs":69282000,"tags":["module","motor-exercicios"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:12:08Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/epic.md","goal":"Entregar e evoluir o módulo Motor de exercícios — criação, edição, catálogo e execução de exercícios no CoachID.","scope":"- Modelos, APIs e UI do motor de exercícios\n- Integração com outros módulos do produto quando necessário","outOfScope":"- Módulos PSE, Wellness, Planeamento e Lineup (epics próprios)","successMetrics":"- Fluxos principais do motor utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"S-001","title":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md"},{"id":"S-005","title":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md"},{"id":"S-006","title":"Duplicar exercício com confirmação e sufixo (copia)","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md"},{"id":"B-011","title":"Texto no vídeo do exercício usa fonte diferente do portal","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md"},{"id":"B-012","title":"Bola teleporta ao associar a jogador durante animação","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md"},{"id":"B-016","title":"Editor — copy/paste não funciona com múltiplos elementos seleccionados","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md"},{"id":"B-022","title":"Exercise editor — PageHeader maximum update depth exceeded","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md"},{"id":"B-026","title":"/pub/media/*.woff2 404 ao exportar/renderizar exercícios","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md"},{"id":"B-027","title":"Editor — copy/paste de seta/curva perde pontos de controlo da curvatura","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md"},{"id":"T-022","title":"Suavizar profundidade do layout de campo 3D","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md"},{"id":"T-029","title":"Lista de exercícios paginada (pastas lazy + pesquisa plana)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md"},{"id":"T-030","title":"Lista de exercícios — sem pasta primeiro, pastas por baixo","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md"},{"id":"T-046","title":"Lista horizontal — thumbnail a preencher a coluna sem espaços em branco","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md"},{"id":"T-047","title":"Lista vertical — thumbnail a 100% do cartão sem cortes","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md"},{"id":"T-048","title":"Guardar exercício — media em background (imagem primeiro, depois vídeo e claro)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md"},{"id":"T-051","title":"Melhorias UI — badge Novo no marketplace, paginação no footer e labels lineup","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md"},{"id":"T-052","title":"Contador de caracteres na descrição e materiais do exercício (aviso soft)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md"}],"commits":[{"sha":"dd2e863","repo":"coachid-taskmark","date":"2026-07-31T00:33:30+01:00","author":"Marco Mendão","message":"add B-016 multi-select copy paste bug"},{"sha":"536a889","repo":"coachid-taskmark","date":"2026-07-31T00:23:10+01:00","author":"Marco Mendão","message":"add T-032 rename exercise categories"},{"sha":"9dd9a07","repo":"coachid-taskmark","date":"2026-07-31T00:20:06+01:00","author":"Marco Mendão","message":"add T-030 unfiled exercises before folders"},{"sha":"6af2419","repo":"coachid-taskmark","date":"2026-07-31T00:12:56+01:00","author":"Marco Mendão","message":"add T-029 exercise list pagination"},{"sha":"d619847","repo":"coachid-taskmark","date":"2026-07-31T00:09:24+01:00","author":"Marco Mendão","message":"add T-028 text element size slider"},{"sha":"2955ff4","repo":"coachid-taskmark","date":"2026-07-30T23:58:14+01:00","author":"Marco Mendão","message":"add B-015 duplicate exercise media regen"},{"sha":"1addec3","repo":"coachid_app_frontend","date":"2026-07-29T12:25:10+01:00","author":"Marco Mendão","message":"fix B-012 ball attach animation teleport"},{"sha":"d9221ca","repo":"coachid_app_frontend","date":"2026-07-29T12:25:10+01:00","author":"Marco Mendão","message":"fix B-012 ball attach animation teleport"},{"sha":"bc6c50c","repo":"coachid-taskmark","date":"2026-07-23T06:41:56+01:00","author":"Marco Mendão","message":"update taskmark board"},{"sha":"9098386","repo":"coachid_app_frontend","date":"2026-07-28T09:39:55Z","author":"Marco Mendão","message":"soften 3d field depth perspective"},{"sha":"7a534e7","repo":"coachid_app_frontend","date":"2026-07-28T09:39:55Z","author":"Marco Mendão","message":"soften 3d field depth perspective"},{"sha":"f2f0d31","repo":"coachid_app_frontend","date":"2026-07-29T06:16:14Z","author":"Marco Mendão","message":"fix exercise video text font to match portal"},{"sha":"1020b7d","repo":"coachid_app_api","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"fix exercise media await and background save"},{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"},{"sha":"d2bc24b","repo":"coachid-taskmark","date":"2026-08-04T23:58:30Z","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"86dd3e0","repo":"coachid_app_frontend","date":"2026-08-05T01:11:42+01:00","author":"Marco Mendão","message":"fix multi-select copy paste in exercise editor"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md":{"id":"B-011","title":"Texto no vídeo do exercício usa fonte diferente do portal","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["motor-exercicios","video","font","export","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-28","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T14:46:10Z","completedAt":"2026-07-29T10:38:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md","description":"","acceptanceCriteria":[{"checked":true,"text":"Todos os `<text>` do pitch no caminho de render (`ExerciseMediaRenderPitchSvg`) têm `font-family` explícito alinhado ao editor/portal"},{"checked":true,"text":"Export SVG→PNG (`exportExerciseSvgToPng`) não depende de herança CSS do documento para tipografia"},{"checked":true,"text":"Texto livre, legendas/captions e números de jogador no vídeo coincidem visualmente com o editor (mesma família)"},{"checked":true,"text":"Preferência: stack partilhada (ex. Inter + fallbacks) e, se necessário, `@font-face` embutido no SVG antes da rasterização"}],"acceptanceCriteriaRaw":"- [x] Todos os `<text>` do pitch no caminho de render (`ExerciseMediaRenderPitchSvg`) têm `font-family` explícito alinhado ao editor/portal\n- [x] Export SVG→PNG (`exportExerciseSvgToPng`) não depende de herança CSS do documento para tipografia\n- [x] Texto livre, legendas/captions e números de jogador no vídeo coincidem visualmente com o editor (mesma família)\n- [x] Preferência: stack partilhada (ex. Inter + fallbacks) e, se necessário, `@font-face` embutido no SVG antes da rasterização","reproSteps":"","fixCriteria":"- [x] Todos os `<text>` do pitch no caminho de render (`ExerciseMediaRenderPitchSvg`) têm `font-family` explícito alinhado ao editor/portal\n- [x] Export SVG→PNG (`exportExerciseSvgToPng`) não depende de herança CSS do documento para tipografia\n- [x] Texto livre, legendas/captions e números de jogador no vídeo coincidem visualmente com o editor (mesma família)\n- [x] Preferência: stack partilhada (ex. Inter + fallbacks) e, se necessário, `@font-face` embutido no SVG antes da rasterização","notes":"Causa: `exportExerciseSvgToPng` serializa o SVG para blob/`<img>` — sem herança do `body` (Inter). No editor, texto livre usa `FREE_TEXT_FONT_FAMILY = \"system-ui, …\"`; em `ExerciseMediaRenderPitchSvg` o texto livre não define `fontFamily`. Playwright (Linux) resolve `system-ui` de forma diferente do macOS.\n\nFicheiros: `exercise-svg-export.ts`, `ExerciseMediaRenderPitchSvg.tsx`, `ExerciseEditorPage.tsx`. Epic E-001.","promptFeedback":[{"index":"1","when":"2026-07-28T14:41:00Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa para resolver fonte do texto no vídeo do exercício diferente do portal."},{"index":"2","when":"2026-07-28T14:46:10Z","kind":"prompt","author":"Marco Mendão","summary":"start-work B-011 — alinhar fonte do texto no vídeo ao portal."},{"index":"3","when":"2026-07-29T10:38:42Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work: fix criteria met (f2f0d31); session closed."}],"commits":[{"sha":"f2f0d31","repo":"coachid_app_frontend","date":"2026-07-29T06:16:14Z","author":"Marco Mendão","message":"fix exercise video text font to match portal"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T14:46:10Z","ended":"2026-07-29T10:38:42Z","summary":"Explicit fontFamily on pitch text + embed @font-face in SVG export (f2f0d31)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md":{"id":"B-012","title":"Bola teleporta ao associar a jogador durante animação","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":187000,"tags":["motor-exercicios","animacao","bola","attachment","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T11:11:02Z","completedAt":"2026-07-29T11:14:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md","description":"No editor de exercício, quando a bola começa livre na frame 1 e na frame 2 é movida e associada a um jogador, a reprodução teleporta a bola para o jogador em vez de animar o deslocamento ao longo do caminho.","acceptanceCriteria":[{"checked":true,"text":"A animação de deslocação corre do sítio da bola na frame 1 até à posição na frame 2."},{"checked":true,"text":"No fim do segmento a bola fica associada ao jogador (snap no canto de attach)."},{"checked":true,"text":"Associação estável ao mesmo jogador em ambas as frames continua a seguir o jogador (sem regressão)."},{"checked":true,"text":"Troca de jogador / detach continua a usar o caminho da bola e a aplicar attach só no fim do segmento quando aplicável."}],"acceptanceCriteriaRaw":"- [x] A animação de deslocação corre do sítio da bola na frame 1 até à posição na frame 2.\n- [x] No fim do segmento a bola fica associada ao jogador (snap no canto de attach).\n- [x] Associação estável ao mesmo jogador em ambas as frames continua a seguir o jogador (sem regressão).\n- [x] Troca de jogador / detach continua a usar o caminho da bola e a aplicar attach só no fim do segmento quando aplicável.","reproSteps":"1. Abrir o editor de exercício.\n2. Adicionar 1 jogador e uma bola; a bola **não** deve estar associada ao jogador.\n3. Adicionar animação (nova keyframe).\n4. Mover a bola e associá-la a um jogador.\n5. Reproduzir a animação.","fixCriteria":"- [x] A animação de deslocação corre do sítio da bola na frame 1 até à posição na frame 2.\n- [x] No fim do segmento a bola fica associada ao jogador (snap no canto de attach).\n- [x] Associação estável ao mesmo jogador em ambas as frames continua a seguir o jogador (sem regressão).\n- [x] Troca de jogador / detach continua a usar o caminho da bola e a aplicar attach só no fim do segmento quando aplicável.","notes":"Causa provável: `ballPlayerAttachmentForPathBlend` / `ballPlayerAttachmentDuringBlend` devolvem `attachTo` para o segmento inteiro quando `!attachFrom && attachTo`, saltando a interpolação do path.","promptFeedback":[{"index":"1","when":"2026-07-29T11:11:02Z","kind":"prompt","author":"Marco Mendão","summary":"create-task + fix: bola teleporta ao associar a jogador na animação (path blend)."},{"index":"2","when":"2026-07-29T11:14:09Z","kind":"feedback","author":"Marco Mendão","summary":"Fix aplicado em exercise-ball-player-attachment (develop + worktree-1)."}],"commits":[{"sha":"1addec3","repo":"coachid_app_frontend","date":"2026-07-29T12:25:10+01:00","author":"Marco Mendão","message":"fix B-012 ball attach animation teleport"},{"sha":"d9221ca","repo":"coachid_app_frontend","date":"2026-07-29T12:25:10+01:00","author":"Marco Mendão","message":"fix B-012 ball attach animation teleport"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T11:11:02Z","ended":"2026-07-29T11:14:09Z","summary":"Fixed path-blend: attach-at-end interpolates ball path and snaps only at segment end."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md":{"id":"B-016","title":"Editor — copy/paste não funciona com múltiplos elementos seleccionados","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"tags":["motor-exercicios","editor","copy-paste","multi-select","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-05T00:05:14Z","completedAt":"2026-08-05T00:07:39Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md","description":"No editor de exercícios, com vários tipos de elementos no pitch (jogadores, materiais, formas, setas, etc.), se o utilizador **seleccionar mais do que um elemento**, a operação **copy/paste** não ocorre. Deveria ser possível **copiar vários elementos de uma só vez** e colá-los.","acceptanceCriteria":[{"checked":true,"text":"Com **múltiplos** elementos seleccionados, copy/paste copia **todos** os seleccionados de uma vez"},{"checked":true,"text":"Funciona para misturas de tipos (jogadores, materiais, formas, setas, texto, etc. conforme suportado pelo editor)"},{"checked":true,"text":"Paste cria novas instâncias com ids/posição coerentes (offset típico do editor, sem partilhar ids com o original)"},{"checked":true,"text":"Selecção única continua a funcionar como hoje"},{"checked":true,"text":"Não regressa multi-selecção, delete ou outras operações em lote já existentes"}],"acceptanceCriteriaRaw":"- [x] Com **múltiplos** elementos seleccionados, copy/paste copia **todos** os seleccionados de uma vez\n- [x] Funciona para misturas de tipos (jogadores, materiais, formas, setas, texto, etc. conforme suportado pelo editor)\n- [x] Paste cria novas instâncias com ids/posição coerentes (offset típico do editor, sem partilhar ids com o original)\n- [x] Selecção única continua a funcionar como hoje\n- [x] Não regressa multi-selecção, delete ou outras operações em lote já existentes","reproSteps":"1. Abrir um exercício com múltiplos elementos (jogadores, materiais, formas, setas, …).\n2. Seleccionar **dois ou mais** elementos (multi-selecção).\n3. Executar copy (ex.: Cmd/Ctrl+C) e depois paste (Cmd/Ctrl+V), ou a acção equivalente do editor.\n4. Observar que o paste **não** duplica o conjunto seleccionado (copy/paste falha / não acontece).","fixCriteria":"- [x] Com **múltiplos** elementos seleccionados, copy/paste copia **todos** os seleccionados de uma vez\n- [x] Funciona para misturas de tipos (jogadores, materiais, formas, setas, texto, etc. conforme suportado pelo editor)\n- [x] Paste cria novas instâncias com ids/posição coerentes (offset típico do editor, sem partilhar ids com o original)\n- [x] Selecção única continua a funcionar como hoje\n- [x] Não regressa multi-selecção, delete ou outras operações em lote já existentes","notes":"Provável gap no clipboard / handler de paste que só trata um `selectedId` em vez do conjunto `selectedIds`.","promptFeedback":[{"index":"1","when":"2026-07-30T23:33:09Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — bug: multi-selecção no editor não faz copy/paste; deve copiar vários elementos de uma vez."},{"index":"2","when":"2026-08-05T00:05:14Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa esta tarefa B-016."},{"index":"3","when":"2026-08-05T00:07:39Z","kind":"feedback","author":"Marco Mendão","summary":"B-016: Cmd+C/V copies all selected items; group offset; remap attachments."}],"commits":[{"sha":"dd2e863","repo":"coachid-taskmark","date":"2026-07-31T00:33:30+01:00","author":"Marco Mendão","message":"add B-016 multi-select copy paste bug"},{"sha":"86dd3e0","repo":"coachid_app_frontend","date":"2026-08-05T01:11:42+01:00","author":"Marco Mendão","message":"fix multi-select copy paste in exercise editor"},{"sha":"f207827","repo":"coachid-taskmark","date":"2026-08-05T00:11:43Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md":{"id":"B-022","title":"Exercise editor — PageHeader maximum update depth exceeded","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":295000,"tags":["motor-exercicios","editor","page-header","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T12:12:00Z","completedAt":"2026-08-03T12:16:55Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md","description":"Opening the exercise editor (expanded route) throws React “Maximum update depth exceeded” from `PageHeaderProvider.setPageHeader` / `PageHeader.useEffect`. The editor becomes unusable. Cause: inline `headerActions` JSX is a new reference every render; `PageHeader`’s effect writes context state; the provider re-renders children; new `actions` retriggers the effect.","acceptanceCriteria":[{"checked":true,"text":"Exercise editor (expanded) loads without maximum update depth error"},{"checked":true,"text":"Top bar still shows the editor title and action buttons"},{"checked":true,"text":"Header updates still work for other pages using `PageHeader` / `setPageHeader`"},{"checked":true,"text":"Fix applied on main `coachid_app_frontend` (not worktrees)"}],"acceptanceCriteriaRaw":"- [x] Exercise editor (expanded) loads without maximum update depth error\n- [x] Top bar still shows the editor title and action buttons\n- [x] Header updates still work for other pages using `PageHeader` / `setPageHeader`\n- [x] Fix applied on main `coachid_app_frontend` (not worktrees)","reproSteps":"1. Open the expanded exercise editor for any exercise.\n2. Observe the runtime error and broken editor UI.","fixCriteria":"- [x] Exercise editor (expanded) loads without maximum update depth error\n- [x] Top bar still shows the editor title and action buttons\n- [x] Header updates still work for other pages using `PageHeader` / `setPageHeader`\n- [x] Fix applied on main `coachid_app_frontend` (not worktrees)","notes":"Prefer fixing `PageHeaderContext` so unstable `actions` React nodes no longer loop (e.g. external store / setter-only subscription), rather than only memoizing one call site.","promptFeedback":[{"index":"1","when":"2026-08-03T12:14:03Z","kind":"prompt","author":"Marco Mendão","summary":"Fix PageHeader infinite update loop breaking exercise editor on main branch (not worktrees)."},{"index":"2","when":"2026-08-03T12:15:14Z","kind":"prompt","author":"Marco Mendão","summary":"Started work: fix PageHeaderContext infinite update depth on main frontend."},{"index":"3","when":"2026-08-03T12:16:55Z","kind":"feedback","author":"Marco Mendão","summary":"Delivered fix on main coachid_app_frontend; exercise editor PageHeader loop resolved."}],"commits":[{"sha":"a511038","repo":"coachid_app_frontend","date":"2026-08-03T12:16:34Z","author":"Marco Mendão","message":"fix B-022 page header infinite update loop"},{"sha":"5e71800","repo":"coachid-taskmark","date":"2026-08-03T12:16:34Z","author":"Marco Mendão","message":"add B-022 page header infinite loop bug"},{"sha":"29dd092","repo":"coachid-taskmark","date":"2026-08-03T12:17:15Z","author":"Marco Mendão","message":"complete B-022 page header loop fix"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T12:12:00Z","ended":"2026-08-03T12:16:55Z","summary":"Fixed PageHeaderContext with external store to stop infinite update loop"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md":{"id":"B-026","title":"/pub/media/*.woff2 404 ao exportar/renderizar exercícios","type":"bug","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":620000,"tags":["motor-exercicios","fonts","pub","media-render"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-04","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T23:49:34Z","completedAt":"2026-08-04T23:59:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md","description":"Em páginas sob `/pub/...` (ex. render de media), o log mostra `GET /pub/media/*.woff2 404`. As fontes Next estão em `/_next/static/media/`.","acceptanceCriteria":[{"checked":true,"text":"URLs de `@font-face` relativas são resolvidas contra o URL da stylesheet (não da página)"},{"checked":true,"text":"Rewrite de segurança `/pub/media/:path*` → `/_next/static/media/:path*`"},{"checked":true,"text":"Deixa de haver 404 sistemáticos em `/pub/media/*.woff2` no fluxo de render/export (após restart do Next)"}],"acceptanceCriteriaRaw":"- [x] URLs de `@font-face` relativas são resolvidas contra o URL da stylesheet (não da página)\n- [x] Rewrite de segurança `/pub/media/:path*` → `/_next/static/media/:path*`\n- [x] Deixa de haver 404 sistemáticos em `/pub/media/*.woff2` no fluxo de render/export (após restart do Next)","reproSteps":"1. Abrir/usar fluxo que faz PNG export ou `/pub/exercise-editor/render`.\n2. Observar no terminal do Next pedidos `GET /pub/media/<hash>.woff2` com 404.","fixCriteria":"- [x] URLs de `@font-face` relativas são resolvidas contra o URL da stylesheet (não da página)\n- [x] Rewrite de segurança `/pub/media/:path*` → `/_next/static/media/:path*`\n- [x] Deixa de haver 404 sistemáticos em `/pub/media/*.woff2` no fluxo de render/export (após restart do Next)","notes":"Causa: `collectEmbeddedFontFaceCss` fazia `new URL(relative, window.location.href)` com página em `/pub/...`.\n\nFix: resolver contra `sheet.href`; rewrite em `next.config.ts`.","promptFeedback":[{"index":"1","when":"2026-08-04T23:48:47Z","kind":"prompt","author":"Marco Mendão","summary":"O que é isto? (404 /pub/media/*.woff2)"},{"index":"2","when":"2026-08-04T23:49:34Z","kind":"prompt","author":"Marco Mendão","summary":"Resolve isto."},{"index":"3","when":"2026-08-04T23:59:54Z","kind":"feedback","author":"Marco Mendão","summary":"Verified done B-026: sheet.href resolve + rewrite; terminal sem 404 recentes."}],"commits":[{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T23:49:34Z","ended":"2026-08-04T23:59:54Z","summary":"Font URL resolve + /pub/media rewrite; no systematic 404s after fix."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md":{"id":"B-027","title":"Editor — copy/paste de seta/curva perde pontos de controlo da curvatura","type":"bug","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"tags":["bug","motor-exercicios","editor","copy-paste","arrow","curve"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:23:44Z","completedAt":"2026-08-11T16:27:50Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md","description":"No editor de exercícios, ao copiar e colar uma seta/curva, a seta colada aparece ligeiramente curvada mesmo quando a original é recta. Os pontos de origem e fim são copiados correctamente, mas os **pontos de controlo da curvatura** não o são (ou são regenerados incorrectamente).","acceptanceCriteria":[{"checked":true,"text":"A seta colada mantém a **mesma curvatura** da seta copiada"},{"checked":true,"text":"Se a seta original **não tem curvatura**, a seta resultante também **não tem curvatura**"},{"checked":true,"text":"Origem, fim e **pontos de controlo** da curva são preservados (ou deslocados de forma consistente no offset do paste, sem alterar a forma relativa)"},{"checked":true,"text":"Comportamento correcto para setas já curvas (a forma relativa é mantida após o paste)"}],"acceptanceCriteriaRaw":"- [x] A seta colada mantém a **mesma curvatura** da seta copiada\n- [x] Se a seta original **não tem curvatura**, a seta resultante também **não tem curvatura**\n- [x] Origem, fim e **pontos de controlo** da curva são preservados (ou deslocados de forma consistente no offset do paste, sem alterar a forma relativa)\n- [x] Comportamento correcto para setas já curvas (a forma relativa é mantida após o paste)","reproSteps":"1. Abrir o editor de exercícios\n2. Adicionar uma seta/curva (recta, sem curvatura intencional)\n3. Seleccionar a seta e fazer **Ctrl+C** / **Ctrl+V** (copy/paste)","fixCriteria":"- [x] A seta colada mantém a **mesma curvatura** da seta copiada\n- [x] Se a seta original **não tem curvatura**, a seta resultante também **não tem curvatura**\n- [x] Origem, fim e **pontos de controlo** da curva são preservados (ou deslocados de forma consistente no offset do paste, sem alterar a forma relativa)\n- [x] Comportamento correcto para setas já curvas (a forma relativa é mantida após o paste)","notes":"- Relacionado com [B-016](B-016-copy-paste-multipla-selecao-elementos.md) (copy/paste no editor).\n- Causa: `translateItemForPaste` deslocava `cx`/`cy` mas não `cx2`/`cy2` (ficavam absolutos via `...item`). Fix: espelhar `moveItemByDelta` com `arrowControlPoints`.","promptFeedback":[{"index":"1","when":"2026-08-10T06:17:23Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task bug — paste de seta/curva fica ligeiramente curvada; origem/fim ok, pontos de controlo da curvatura não."},{"index":"2","when":"2026-08-11T16:23:44Z","kind":"prompt","author":"Marco Mendão","summary":"Resolve o bug B-027 e B-028"}],"commits":[{"sha":"3a23b1f","repo":"coachid_app_frontend","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"fix arrow paste curve and datacenter country prefill"},{"sha":"cdb1892","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"fix arrow paste curve and datacenter country prefill"},{"sha":"b724190","repo":"coachid-taskmark","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:23:44Z","ended":"2026-08-11T16:25:47Z","summary":"shared-batch: 2 of ~4min by points — translateItemForPaste offsets both cubic handles"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md":{"id":"T-022","title":"Suavizar profundidade do layout de campo 3D","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":0,"tags":["motor-exercicios","field","perspective","ui"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-28","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T09:37:11Z","completedAt":"2026-07-28T09:37:11Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md","description":"No motor de exercícios, o layout de campo 3D em profundidade (`depth`) tem perspectiva demasiado agressiva: a linha de fundo (topo) fica com pouca largura. Suavizar a profundidade para o campo ao fundo ter mais largura, mantendo o efeito 3D.","acceptanceCriteria":[{"checked":true,"text":"No preset de campo 3D em profundidade, a linha de fundo (far) é claramente mais larga do que o valor actual"},{"checked":true,"text":"A perspectiva continua perceptível (não fica rectangular como `depthHorizontal`)"},{"checked":true,"text":"Marcações projectadas (áreas, círculos, balizas) acompanham a nova razão de perspectiva"}],"acceptanceCriteriaRaw":"- [x] No preset de campo 3D em profundidade, a linha de fundo (far) é claramente mais larga do que o valor actual\n- [x] A perspectiva continua perceptível (não fica rectangular como `depthHorizontal`)\n- [x] Marcações projectadas (áreas, círculos, balizas) acompanham a nova razão de perspectiva","reproSteps":"","fixCriteria":"","notes":"Constante principal: `FAR_HALF_W` em `PerspectiveFieldSvg.tsx` (era `21`, agora `38` vs `NEAR_HALF_W` `54` ≈ 70%). Epic E-001.","promptFeedback":[{"index":"1","when":"2026-07-28T09:37:11Z","kind":"prompt","author":"Marco Mendão","summary":"Criar task e suavizar profundidade do campo 3D — fundo com mais largura."},{"index":"2","when":"2026-07-28T09:37:11Z","kind":"feedback","author":"Marco Mendão","summary":"FAR_HALF_W aumentado para 38; perspectiva mais ténue."}],"commits":[{"sha":"9098386","repo":"coachid_app_frontend","date":"2026-07-28T09:39:55Z","author":"Marco Mendão","message":"soften 3d field depth perspective"},{"sha":"7a534e7","repo":"coachid_app_frontend","date":"2026-07-28T09:39:55Z","author":"Marco Mendão","message":"soften 3d field depth perspective"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T09:37:11Z","ended":"2026-07-28T09:37:11Z","summary":"FAR_HALF_W 21→38 (~70% near width)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md":{"id":"T-029","title":"Lista de exercícios paginada (pastas lazy + pesquisa plana)","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":7,"actualMs":475000,"tags":["motor-exercicios","list","pagination","folders","performance","search"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T15:10:14Z","completedAt":"2026-08-04T15:18:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md","description":"A lista de exercícios no módulo deve ser **paginada** (default **10** por página): paginação **dentro de cada pasta**, paginação **geral** para exercícios **fora de pastas**, e carregamento **lazy** dos exercícios de uma pasta só quando o utilizador a abre. Em **pesquisa/filtro**, mostrar lista **plana sem pastas**, também paginada.","acceptanceCriteria":[{"checked":true,"text":"Existe paginação na lista de exercícios **fora de pastas** (raiz / sem pasta)"},{"checked":true,"text":"Existe paginação **independente dentro de cada pasta**"},{"checked":true,"text":"Valor por defeito da paginação: **10 exercícios** por página"},{"checked":true,"text":"Ao abrir o módulo, os exercícios **dentro das pastas não são obtidos** até o utilizador **abrir** essa pasta (lazy get) — para manter a abertura rápida"},{"checked":true,"text":"Ao abrir uma pasta, os exercícios dessa pasta são obtidos (paginados) nesse momento"},{"checked":true,"text":"Quando o utilizador aplica **pesquisa ou filtro**, a UI mostra uma **lista plana de exercícios sem pastas**"},{"checked":true,"text":"Essa lista de pesquisa/filtro é **também paginada** (default 10)"},{"checked":true,"text":"Controlo de página / total coerente com o padrão de paginação do produto"}],"acceptanceCriteriaRaw":"- [x] Existe paginação na lista de exercícios **fora de pastas** (raiz / sem pasta)\n- [x] Existe paginação **independente dentro de cada pasta**\n- [x] Valor por defeito da paginação: **10 exercícios** por página\n- [x] Ao abrir o módulo, os exercícios **dentro das pastas não são obtidos** até o utilizador **abrir** essa pasta (lazy get) — para manter a abertura rápida\n- [x] Ao abrir uma pasta, os exercícios dessa pasta são obtidos (paginados) nesse momento\n- [x] Quando o utilizador aplica **pesquisa ou filtro**, a UI mostra uma **lista plana de exercícios sem pastas**\n- [x] Essa lista de pesquisa/filtro é **também paginada** (default 10)\n- [x] Controlo de página / total coerente com o padrão de paginação do produto","reproSteps":"","fixCriteria":"","notes":"API e UI do catálogo de exercícios do motor; pasta = agrupamento já existente no módulo. Lazy = não prefetch do conteúdo de pastas fechadas no load inicial.","promptFeedback":[{"index":"1","when":"2026-07-30T23:12:32Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — lista exercícios paginada (10); por pasta + fora de pastas; lazy get ao abrir pasta; pesquisa/filtro = lista plana paginada."},{"index":"2","when":"2026-08-04T15:10:14Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa T-029 — lista exercícios paginada (pastas lazy + pesquisa plana)."},{"index":"3","when":"2026-08-04T15:18:09Z","kind":"feedback","author":"Marco Mendão","summary":"Implementação T-029 concluída (API + UI worktree-1)."}],"commits":[{"sha":"a7b6446","repo":"coachid_app_api","date":"2026-08-04T17:39:58+01:00","author":"Marco Mendão","message":"add exercise and marketplace list pagination"},{"sha":"fa1ddbb","repo":"coachid_app_frontend","date":"2026-08-04T17:39:59+01:00","author":"Marco Mendão","message":"add exercise list pagination and horizontal card layout"},{"sha":"9a68106","repo":"coachid-taskmark","date":"2026-08-04T17:40:00+01:00","author":"Marco Mendão","message":"sync taskmark board for T-029 T-030"},{"sha":"6af2419","repo":"coachid-taskmark","date":"2026-07-31T00:12:56+01:00","author":"Marco Mendão","message":"add T-029 exercise list pagination"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T15:10:14Z","ended":"2026-08-04T15:18:09Z","summary":"Paginação lista exercícios: API page/folderId, root+pasta lazy, pesquisa plana."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md":{"id":"T-030","title":"Lista de exercícios — sem pasta primeiro, pastas por baixo","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":0,"actualMs":16000,"tags":["motor-exercicios","list","folders","ux","ordering"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T16:16:19Z","completedAt":"2026-08-04T16:16:35Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md","description":"Na lista de exercícios (vista com pastas), os **exercícios sem pasta** devem aparecer **primeiro**; as **pastas** ficam **por baixo**.","acceptanceCriteria":[{"checked":true,"text":"Na vista normal (com pastas), a secção/lista de exercícios **fora de pastas** é mostrada **acima** das pastas"},{"checked":true,"text":"As pastas aparecem **depois** dos exercícios sem pasta"},{"checked":true,"text":"Comportamento coerente com a paginação da raiz / pastas (T-029) quando ambos estiverem implementados"},{"checked":true,"text":"A vista de pesquisa/filtro (lista plana) não é afectada de forma incorrecta por esta regra de ordenação de pastas"}],"acceptanceCriteriaRaw":"- [x] Na vista normal (com pastas), a secção/lista de exercícios **fora de pastas** é mostrada **acima** das pastas\n- [x] As pastas aparecem **depois** dos exercícios sem pasta\n- [x] Comportamento coerente com a paginação da raiz / pastas (T-029) quando ambos estiverem implementados\n- [x] A vista de pesquisa/filtro (lista plana) não é afectada de forma incorrecta por esta regra de ordenação de pastas","reproSteps":"","fixCriteria":"","notes":"Relacionado com T-029 (paginação e lazy pastas). Apenas ordem de apresentação na UI da lista com pastas.","promptFeedback":[{"index":"1","when":"2026-07-30T23:19:46Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — na lista, exercícios sem pasta primeiro; pastas por baixo."},{"index":"2","when":"2026-08-04T16:16:19Z","kind":"prompt","author":"Marco Mendão","summary":"Os meus exercícios devem aparecer primeiro que as pastas."},{"index":"3","when":"2026-08-04T16:16:35Z","kind":"feedback","author":"Marco Mendão","summary":"Ordem UI: Os meus exercícios primeiro."}],"commits":[{"sha":"a7b6446","repo":"coachid_app_api","date":"2026-08-04T17:39:58+01:00","author":"Marco Mendão","message":"add exercise and marketplace list pagination"},{"sha":"fa1ddbb","repo":"coachid_app_frontend","date":"2026-08-04T17:39:59+01:00","author":"Marco Mendão","message":"add exercise list pagination and horizontal card layout"},{"sha":"9a68106","repo":"coachid-taskmark","date":"2026-08-04T17:40:00+01:00","author":"Marco Mendão","message":"sync taskmark board for T-029 T-030"},{"sha":"9dd9a07","repo":"coachid-taskmark","date":"2026-07-31T00:20:06+01:00","author":"Marco Mendão","message":"add T-030 unfiled exercises before folders"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T16:16:19Z","ended":"2026-08-04T16:16:35Z","summary":"Raiz (Os meus exercícios) renderizada acima das pastas."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md":{"id":"T-046","title":"Lista horizontal — thumbnail a preencher a coluna sem espaços em branco","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":15,"actualMinutes":13,"actualMs":780000,"tags":["motor-exercicios","list","layout","thumbnail","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-04","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T16:42:31Z","completedAt":"2026-08-04T16:55:31Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md","description":"No layout **horizontal** dos cartões de exercício (e marketplace), a thumbnail deve ocupar o máximo de espaço possível na coluna — sem faixas em branco. Alargar a coluna do thumb se for preciso.","acceptanceCriteria":[{"checked":true,"text":"No layout horizontal (md+), a coluna do thumbnail usa aspect 120/80 (14rem) sem crop do campo"},{"checked":true,"text":"O painel de informação (título, meta, descrição) permanece visível ao lado do thumb"},{"checked":true,"text":"Layout vertical e mobile empilhado mantêm o aspect ratio habitual"},{"checked":true,"text":"Skeleton e cartões marketplace alinhados com o mesmo comportamento"}],"acceptanceCriteriaRaw":"- [x] No layout horizontal (md+), a coluna do thumbnail usa aspect 120/80 (14rem) sem crop do campo\n- [x] O painel de informação (título, meta, descrição) permanece visível ao lado do thumb\n- [x] Layout vertical e mobile empilhado mantêm o aspect ratio habitual\n- [x] Skeleton e cartões marketplace alinhados com o mesmo comportamento","reproSteps":"","fixCriteria":"","notes":"Follow-up ao layout horizontal dos cartões (T-029). Solução final: coluna fixa 14rem + aspect 120/80 (evitar cover a esticar a altura do cartão).","promptFeedback":[{"index":"1","when":"2026-08-04T16:42:31Z","kind":"prompt","author":"Marco Mendão","summary":"Thumbnail no layout horizontal deve ocupar o máximo espaço possível; alargar coluna se necessário."},{"index":"2","when":"2026-08-04T16:49:24Z","kind":"prompt","author":"Marco Mendão","summary":"Cover corta em cima/baixo — ajustar largura das colunas para o aspect do campo sem crop."},{"index":"3","when":"2026-08-04T16:51:00Z","kind":"prompt","author":"Marco Mendão","summary":"Cartões só com thumb cortada; restaurar info e thumbs sem cortes."},{"index":"4","when":"2026-08-04T16:55:31Z","kind":"feedback","author":"Marco Mendão","summary":"/commit-all — thumb 14rem aspect 120/80 sem crop; info restaurada."}],"commits":[{"sha":"e4093f4","repo":"coachid_app_frontend","date":"2026-08-04T17:55:30+01:00","author":"Marco Mendão","message":"fix horizontal exercise card thumbnail aspect"},{"sha":"770e203","repo":"coachid-taskmark","date":"2026-08-04T17:56:00+01:00","author":"Marco Mendão","message":"sync taskmark board for T-046"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T16:42:31Z","ended":"2026-08-04T16:55:31Z","summary":"Coluna thumb 14rem + aspect 120/80; sem crop; info do cartão restaurada."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md":{"id":"T-047","title":"Lista vertical — thumbnail a 100% do cartão sem cortes","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2344000,"tags":["motor-exercicios","list","layout","thumbnail","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-04","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T16:56:32Z","completedAt":"2026-08-04T17:35:36Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md","description":"No layout **vertical**, a thumbnail deve ocupar **100%** da largura do cartão (área de media), com aspect 120/80 e **sem cortes** do campo — mesmo princípio do T-046 no horizontal.","acceptanceCriteria":[{"checked":true,"text":"No layout vertical, o thumb vai de bordo a bordo (sem padding interno na área de media)"},{"checked":true,"text":"Aspect 120/80 mantido — campo completo sem crop"},{"checked":true,"text":"Acções overlay e badges continuam utilizáveis"},{"checked":true,"text":"Marketplace e skeleton alinhados"}],"acceptanceCriteriaRaw":"- [x] No layout vertical, o thumb vai de bordo a bordo (sem padding interno na área de media)\n- [x] Aspect 120/80 mantido — campo completo sem crop\n- [x] Acções overlay e badges continuam utilizáveis\n- [x] Marketplace e skeleton alinhados","reproSteps":"","fixCriteria":"","notes":"Espelha T-046 para o layout vertical.","promptFeedback":[{"index":"1","when":"2026-08-04T16:56:32Z","kind":"prompt","author":"Marco Mendão","summary":"Mesmo tratamento no layout vertical: imagens a 100% do cartão sem cortes."},{"index":"2","when":"2026-08-04T17:35:36Z","kind":"feedback","author":"Marco Mendão","summary":"/commit-all — vertical thumb full-bleed aceite."}],"commits":[{"sha":"5bb1f3d","repo":"coachid_app_frontend","date":"2026-08-04T18:35:39+01:00","author":"Marco Mendão","message":"fix vertical exercise card thumbnail full bleed"},{"sha":"7b0cf64","repo":"coachid-taskmark","date":"2026-08-04T18:36:01+01:00","author":"Marco Mendão","message":"sync taskmark board for T-047"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T16:56:32Z","ended":"2026-08-04T17:35:36Z","summary":"Thumb vertical full-bleed (p-0, rounded-none, aspect 120/80)."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md":{"id":"T-048","title":"Guardar exercício — media em background (imagem primeiro, depois vídeo e claro)","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"tags":["motor-exercicios","media","preview","performance","api","background"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-04","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T23:52:39Z","completedAt":"2026-08-04T23:55:40Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md","description":"Ao **guardar** um exercício, a API deve gerar imagens e vídeos em **background** para o save não demorar demasiado.\n\nOrdem pretendida:\n\n1. Gerar primeiro a **imagem** do exercício (preview principal / superfície default, tipicamente green)\n2. **Libertar o request** da API (o cliente recebe resposta sem esperar o resto)\n3. Em background: gerar o **vídeo** (se o exercício for animado / tiver motion) e a **imagem em claro** (superfície white, usada no relatório da unidade de treino)\n\nNão bloquear o save à espera do vídeo nem da imagem em claro.","acceptanceCriteria":[{"checked":true,"text":"O endpoint de create/update (guardar) **não espera** a geração completa de vídeo nem da imagem em claro antes de responder"},{"checked":true,"text":"A **imagem principal** do exercício é gerada com prioridade (antes ou imediatamente a seguir ao persistir, de forma a não alongar o request de forma desnecessária face ao objectivo de save rápido — preferência: libertar o request cedo; a imagem principal pode concluir em background desde que o save em si seja rápido)"},{"checked":true,"text":"Com motion: o **vídeo** é gerado **em background** após a libertação do request"},{"checked":true,"text":"A **imagem em claro** (white / report) é gerada **em background** após a libertação do request"},{"checked":true,"text":"O fluxo de **duplicar** (B-015) continua alinhado: regeneração sem copiar S3; preview utilizável sem bloquear save/duplicação indevidamente"},{"checked":true,"text":"Listagem/editor mostram preview assim que a imagem principal estiver disponível; vídeo quando o job async terminar"}],"acceptanceCriteriaRaw":"- [x] O endpoint de create/update (guardar) **não espera** a geração completa de vídeo nem da imagem em claro antes de responder\n- [x] A **imagem principal** do exercício é gerada com prioridade (antes ou imediatamente a seguir ao persistir, de forma a não alongar o request de forma desnecessária face ao objectivo de save rápido — preferência: libertar o request cedo; a imagem principal pode concluir em background desde que o save em si seja rápido)\n- [x] Com motion: o **vídeo** é gerado **em background** após a libertação do request\n- [x] A **imagem em claro** (white / report) é gerada **em background** após a libertação do request\n- [x] O fluxo de **duplicar** (B-015) continua alinhado: regeneração sem copiar S3; preview utilizável sem bloquear save/duplicação indevidamente\n- [x] Listagem/editor mostram preview assim que a imagem principal estiver disponível; vídeo quando o job async terminar","reproSteps":"","fixCriteria":"","notes":"Create/update normal: fire-and-forget após persist. Duplicate (B-015): `awaitPreviewImages` espera só a PNG green. Job Playwright: green → white → vídeo.","promptFeedback":[{"index":"1","when":"2026-08-04T23:42:56Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — ao salvar, gerar media em background: imagem primeiro, libertar request, depois vídeo (se animado) e imagem em claro (report) em background."},{"index":"2","when":"2026-08-04T23:52:39Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa a tarefa T-048."},{"index":"3","when":"2026-08-04T23:55:40Z","kind":"feedback","author":"Marco Mendão","summary":"Save rápido: FE sem upload PNG; API fire-and-forget green→white→video; poll soft refresh; duplicate mantém awaitPreviewImages."}],"commits":[{"sha":"1020b7d","repo":"coachid_app_api","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"fix exercise media await and background save"},{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"},{"sha":"d2bc24b","repo":"coachid-taskmark","date":"2026-08-04T23:58:30Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md":{"id":"T-051","title":"Melhorias UI — badge Novo no marketplace, paginação no footer e labels lineup","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["ui","motor-exercicios","marketplace","pagination","lineup","i18n","microciclo","planeamento"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T00:03:29Z","completedAt":"2026-08-12T00:04:29Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md","description":"Pequenas melhorias de UI no catálogo de exercícios e correções de copy:\n\n1. **Marketplace — badge «Novo»:** no tab controller da lista de exercícios, o tab do marketplace deve mostrar um badge «Novo» para sinalizar que a funcionalidade é nova. O badge deve permanecer activo durante **3 meses** a partir da data de implementação (depois desaparece automaticamente).\n2. **Paginação no footer dos contentores:** cada contentor de exercícios (pasta e o contentor de exercícios sem pasta) deve ter um **footer** com a paginação desse contentor (em vez de controlos soltos / fora do contentor, se for o caso actual).\n3. **Lineup — labels de posição:** nos campos de posição, «Defesa Direita» e «Defesa Esquerda» devem passar a «Defesa Direito» e «Defesa Esquerdo».\n4. **Microciclo — prefixo:** o prefixo do microciclo deve ser **`m`** em vez de **`μ`**.\n5. **Traduções em falta:** definir traduções para as labels `page.exercises.timingDuration`, `page.exercises.timingRecovery` e `page.exercises.timingRepetitions`.","acceptanceCriteria":[{"checked":true,"text":"O tab do marketplace na lista de exercícios mostra um badge visível com o texto «Novo» (i18n conforme o resto do produto)"},{"checked":true,"text":"O badge «Novo» está activo durante os **próximos 3 meses** a contar da data de implementação e deixa de ser mostrado após essa janela (sem remoção manual de código em produção)"},{"checked":true,"text":"Cada pasta de exercícios tem um **footer** com a paginação desse contentor"},{"checked":true,"text":"O contentor de exercícios **sem pasta** tem um **footer** com a sua paginação"},{"checked":true,"text":"A paginação por contentor continua coerente com o comportamento existente (ex. T-029: independente por pasta / sem pasta)"},{"checked":true,"text":"No lineup, a posição «Defesa Direita» passa a «Defesa Direito»"},{"checked":true,"text":"No lineup, a posição «Defesa Esquerda» passa a «Defesa Esquerdo»"},{"checked":true,"text":"Labels correctas em PT (e restantes locales se existirem chaves equivalentes)"},{"checked":true,"text":"O prefixo do microciclo é **`m`** (não `μ`) em todos os sítios onde esse prefixo é mostrado (calendário, chips, tooltips, export, etc.)"},{"checked":true,"text":"Existem traduções para `page.exercises.timingDuration`, `page.exercises.timingRecovery` e `page.exercises.timingRepetitions` em todos os locales do produto"}],"acceptanceCriteriaRaw":"- [x] O tab do marketplace na lista de exercícios mostra um badge visível com o texto «Novo» (i18n conforme o resto do produto)\n- [x] O badge «Novo» está activo durante os **próximos 3 meses** a contar da data de implementação e deixa de ser mostrado após essa janela (sem remoção manual de código em produção)\n- [x] Cada pasta de exercícios tem um **footer** com a paginação desse contentor\n- [x] O contentor de exercícios **sem pasta** tem um **footer** com a sua paginação\n- [x] A paginação por contentor continua coerente com o comportamento existente (ex. T-029: independente por pasta / sem pasta)\n- [x] No lineup, a posição «Defesa Direita» passa a «Defesa Direito»\n- [x] No lineup, a posição «Defesa Esquerda» passa a «Defesa Esquerdo»\n- [x] Labels correctas em PT (e restantes locales se existirem chaves equivalentes)\n- [x] O prefixo do microciclo é **`m`** (não `μ`) em todos os sítios onde esse prefixo é mostrado (calendário, chips, tooltips, export, etc.)\n- [x] Existem traduções para `page.exercises.timingDuration`, `page.exercises.timingRecovery` e `page.exercises.timingRepetitions` em todos os locales do produto","reproSteps":"","fixCriteria":"","notes":"- Relacionado com [T-029](T-029-lista-exercicios-paginacao-pastas-lazy.md) (paginação por pasta / sem pasta).\n- A correção de labels do lineup toca o domínio E-005; o prefixo do microciclo toca E-004 (planeamento); incluir na mesma entrega por ser copy mínima.\n- Preferir data de expiração do badge configurável (constante / feature flag com data fim) para evitar hardcode opaco.","promptFeedback":[{"index":"1","when":"2026-08-10T06:13:50Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — badge Novo no tab marketplace (3 meses); footer com paginação por contentor (pasta e sem pasta); lineup Defesa Direito/Esquerdo."},{"index":"2","when":"2026-08-10T06:39:30Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar a T-051: prefixo do microciclo «μ» → «m»."},{"index":"3","when":"2026-08-10T06:40:30Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar a T-051: traduções para page.exercises.timingDuration / timingRecovery / timingRepetitions."},{"index":"1","when":"2026-08-12T00:03:29Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa as tarefas T-051, T-052, T-053, T-054"}],"commits":[{"sha":"f50bae5","repo":"coachid_app_frontend","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"},{"sha":"064e451","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T00:03:29Z","ended":"2026-08-12T00:04:29Z","summary":"Marketplace Novo badge, pagination footers, lineup RB/LB, micro m, timing i18n; shared-batch: 1 of 4min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md":{"id":"T-052","title":"Contador de caracteres na descrição e materiais do exercício (aviso soft)","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":60000,"tags":["ui","motor-exercicios","editor","description","materials","character-limit"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T00:03:29Z","completedAt":"2026-08-12T00:05:29Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md","description":"No motor de exercícios, os campos **descrição** e **materiais** devem mostrar um contador de caracteres no estilo `actual/limite`:\n\n- Descrição: `0/600`\n- Materiais: `0/65`\n\nSe o utilizador ultrapassar o limite, mostrar uma mensagem de aviso por baixo do campo a indicar que o texto é muito longo e que poderá aparecer cortado em alguns documentos (ex. relatório de unidade de treino). O limite é **soft**: não deve impedir o utilizador de escrever além do limite se assim o quiser.","acceptanceCriteria":[{"checked":true,"text":"O campo **descrição** mostra um contador no formato `n/600` actualizado em tempo real"},{"checked":true,"text":"O campo **materiais** mostra um contador no formato `n/65` actualizado em tempo real"},{"checked":true,"text":"Quando `n` excede o limite do campo, aparece uma mensagem de aviso por baixo a dizer que o texto é muito longo e que poderá aparecer cortado em alguns documentos (ex. relatório de unidade de treino)"},{"checked":true,"text":"Ultrapassar o limite **não bloqueia** a escrita, o guardar, nem a validação do formulário"},{"checked":true,"text":"Mensagens/contadores com i18n alinhado ao resto do produto"}],"acceptanceCriteriaRaw":"- [x] O campo **descrição** mostra um contador no formato `n/600` actualizado em tempo real\n- [x] O campo **materiais** mostra um contador no formato `n/65` actualizado em tempo real\n- [x] Quando `n` excede o limite do campo, aparece uma mensagem de aviso por baixo a dizer que o texto é muito longo e que poderá aparecer cortado em alguns documentos (ex. relatório de unidade de treino)\n- [x] Ultrapassar o limite **não bloqueia** a escrita, o guardar, nem a validação do formulário\n- [x] Mensagens/contadores com i18n alinhado ao resto do produto","reproSteps":"","fixCriteria":"","notes":"Limites de referência (soft): descrição 600, materiais 65 — alinhados ao truncamento esperado em documentos exportados (ex. relatório UT).","promptFeedback":[{"index":"1","when":"2026-08-10T06:31:19Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — contador 0/600 descrição e 0/65 materiais; aviso soft se ultrapassar (texto longo / cortado em docs como relatório UT); não bloquear input."},{"index":"2","when":"2026-08-12T00:03:29Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa as tarefas T-051, T-052, T-053, T-054"}],"commits":[{"sha":"f50bae5","repo":"coachid_app_frontend","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"},{"sha":"064e451","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T00:04:29Z","ended":"2026-08-12T00:05:29Z","summary":"Soft char counters description 600 / materials 65; shared-batch: 1 of 4min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md":{"id":"S-001","title":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","type":"story","status":"done","priority":"medium","size":"M","points":5,"estimateMinutes":570,"actualMinutes":561,"actualMs":33710000,"tags":["motor-exercicios","ui","typography"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:32:33Z","completedAt":"2026-08-04T23:59:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md","userStory":"Como utilizador do editor de exercícios, quero que o texto dos elementos e as etiquetas inferiores estejam a 180% do tamanho actual, para que o conteúdo seja mais legível.","acceptanceCriteria":[{"checked":true,"text":"Elementos de texto renderizam a 180% do tamanho actual"},{"checked":true,"text":"Etiquetas em baixo dos elementos renderizam a 180% do tamanho actual"},{"checked":true,"text":"Restantes tipos de elemento sem alteração indesejada de escala"}],"acceptanceCriteriaRaw":"- [x] Elementos de texto renderizam a 180% do tamanho actual\n- [x] Etiquetas em baixo dos elementos renderizam a 180% do tamanho actual\n- [x] Restantes tipos de elemento sem alteração indesejada de escala","tasksMarkdown":"- [T-001](items/T-001-texto-elemento-180.md) — Aumentar tamanho do elemento de texto para 180%\n- [T-002](items/T-002-etiqueta-inferior-180.md) — Aumentar tamanho das etiquetas inferiores para 180%\n- [T-028](items/T-028-redimensionar-texto-slider.md) — Redimensionar tamanho do elemento de texto com slider","children":[{"id":"T-001","title":"Aumentar tamanho do elemento de texto para 180%","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-001-texto-elemento-180.md"},{"id":"T-002","title":"Aumentar tamanho das etiquetas inferiores para 180%","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-002-etiqueta-inferior-180.md"},{"id":"T-028","title":"Redimensionar tamanho do elemento de texto com slider","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-028-redimensionar-texto-slider.md"}],"promptFeedback":[{"index":"3","when":"2026-07-28T07:36:26Z","kind":"feedback","author":"Marco Mendão","summary":"S-001 delivered via T-001/T-002."},{"index":"2","when":"2026-07-28T07:32:33Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-001 e S-006."},{"index":"1","when":"2026-07-23T04:51:58Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefas no epic exercícios: texto a 180%; etiquetas em baixo a 180%."}],"commits":[{"sha":"d619847","repo":"coachid-taskmark","date":"2026-07-31T00:09:24+01:00","author":"Marco Mendão","message":"add T-028 text element size slider"},{"sha":"884c04e","repo":"coachid_app_frontend","date":"2026-07-28T07:35:52Z","author":"Marco Mendão","message":"scale text labels 180% and add exercise duplicate"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:32:33Z","ended":"2026-07-28T07:32:33Z","summary":"Parent rollup (0ms); billable on T-001/T-002 shared-batch."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-001-texto-elemento-180.md":{"id":"T-001","title":"Aumentar tamanho do elemento de texto para 180%","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":46000,"tags":["motor-exercicios","ui","typography","text-element"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-001","epic":"E-001","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:32:33Z","completedAt":"2026-07-28T07:36:26Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-001-texto-elemento-180.md","description":"No motor de exercícios, o elemento de texto deve passar a renderizar com **180% do tamanho actual** (escala 1.8× face ao valor vigente).","acceptanceCriteria":[{"checked":true,"text":"Tamanho tipográfico do elemento de texto é 180% do valor actual"},{"checked":true,"text":"Alteração visível no editor/canvas de exercícios"},{"checked":true,"text":"Sem regressão noutros tipos de elemento"}],"acceptanceCriteriaRaw":"- [x] Tamanho tipográfico do elemento de texto é 180% do valor actual\n- [x] Alteração visível no editor/canvas de exercícios\n- [x] Sem regressão noutros tipos de elemento","reproSteps":"","fixCriteria":"","notes":"Âmbito: epic E-001 Motor de exercícios / story S-001.","promptFeedback":[{"index":"3","when":"2026-07-28T07:36:26Z","kind":"feedback","author":"Marco Mendão","summary":"T-001 delivered."},{"index":"2","when":"2026-07-28T07:32:33Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar com S-001/S-006 batch."},{"index":"1","when":"2026-07-23T04:51:58Z","kind":"prompt","author":"Marco Mendão","summary":"Elemento de texto deve aumentar para 180% do tamanho actual."}],"commits":[{"sha":"884c04e","repo":"coachid_app_frontend","date":"2026-07-28T07:35:52Z","author":"Marco Mendão","message":"scale text labels 180% and add exercise duplicate"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:32:33Z","ended":"2026-07-28T07:33:19Z","summary":"Text element font base ×1.8. shared-batch: 46744 of 233717ms by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-002-etiqueta-inferior-180.md":{"id":"T-002","title":"Aumentar tamanho das etiquetas inferiores para 180%","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":46000,"tags":["motor-exercicios","ui","typography","bottom-label"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-001","epic":"E-001","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:32:33Z","completedAt":"2026-07-28T07:36:26Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-002-etiqueta-inferior-180.md","description":"Nos elementos do motor de exercícios que têm **etiqueta em baixo**, essa etiqueta deve passar a renderizar com **180% do tamanho actual** (escala 1.8× face ao valor vigente).","acceptanceCriteria":[{"checked":true,"text":"Etiquetas inferiores dos elementos estão a 180% do tamanho actual"},{"checked":true,"text":"Alteração visível nos elementos que exibem etiqueta em baixo"},{"checked":true,"text":"Sem regressão em elementos sem etiqueta inferior"}],"acceptanceCriteriaRaw":"- [x] Etiquetas inferiores dos elementos estão a 180% do tamanho actual\n- [x] Alteração visível nos elementos que exibem etiqueta em baixo\n- [x] Sem regressão em elementos sem etiqueta inferior","reproSteps":"","fixCriteria":"","notes":"Âmbito: epic E-001 Motor de exercícios / story S-001.","promptFeedback":[{"index":"3","when":"2026-07-28T07:36:26Z","kind":"feedback","author":"Marco Mendão","summary":"T-002 delivered."},{"index":"2","when":"2026-07-28T07:32:33Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar com S-001/S-006 batch."},{"index":"1","when":"2026-07-23T04:51:58Z","kind":"prompt","author":"Marco Mendão","summary":"Etiquetas em baixo dos elementos devem passar a 180% do tamanho actual."}],"commits":[{"sha":"884c04e","repo":"coachid_app_frontend","date":"2026-07-28T07:35:52Z","author":"Marco Mendão","message":"scale text labels 180% and add exercise duplicate"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:32:33Z","ended":"2026-07-28T07:33:19Z","summary":"Bottom caption font base ×1.8. shared-batch: 46743 of 233717ms by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-028-redimensionar-texto-slider.md":{"id":"T-028","title":"Redimensionar tamanho do elemento de texto com slider","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":560,"actualMinutes":560,"actualMs":33618000,"tags":["motor-exercicios","ui","typography","text","slider"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-001","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T16:00:53Z","completedAt":"2026-08-04T19:00:27Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-028-redimensionar-texto-slider.md","description":"No motor de exercícios, o elemento de **texto** deve permitir **redimensionar o tamanho do texto** via um **slider** nas opções do elemento seleccionado, à semelhança do controlo de tamanho das **labels dos jogadores**.\n\nA **cor do texto** deve aparecer na tab **Estilo** (não na tab Texto).","acceptanceCriteria":[{"checked":true,"text":"Com um elemento de texto seleccionado, a tab **Texto** inclui um **slider** de tamanho de texto"},{"checked":true,"text":"O slider comporta-se de forma análoga ao das **labels dos jogadores** (UX, intervalo/passos e feedback visual coerentes com o editor)"},{"checked":true,"text":"Alterar o slider actualiza o tamanho do texto no pitch / preview de imediato"},{"checked":true,"text":"A **caixa de selecção** (tracejado) acompanha o tamanho do texto"},{"checked":true,"text":"O tamanho escolhido é **persistido** com o exercício (guardar / reabrir mantém o valor)"},{"checked":true,"text":"O picker **Cor do texto** aparece na tab **Estilo** (não na tab Texto) para elementos de texto"},{"checked":true,"text":"Não regressa o comportamento das labels de jogadores nem de outros tipos de elemento"}],"acceptanceCriteriaRaw":"- [x] Com um elemento de texto seleccionado, a tab **Texto** inclui um **slider** de tamanho de texto\n- [x] O slider comporta-se de forma análoga ao das **labels dos jogadores** (UX, intervalo/passos e feedback visual coerentes com o editor)\n- [x] Alterar o slider actualiza o tamanho do texto no pitch / preview de imediato\n- [x] A **caixa de selecção** (tracejado) acompanha o tamanho do texto\n- [x] O tamanho escolhido é **persistido** com o exercício (guardar / reabrir mantém o valor)\n- [x] O picker **Cor do texto** aparece na tab **Estilo** (não na tab Texto) para elementos de texto\n- [x] Não regressa o comportamento das labels de jogadores nem de outros tipos de elemento","reproSteps":"","fixCriteria":"","notes":"Referência UX: slider de tamanho de label de jogador no popover/painel de selecção do editor (`ExerciseEditorSelectionPopover` / controlos de token label size).","promptFeedback":[{"index":"1","when":"2026-07-30T23:09:00Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — elemento texto redimensionável com slider nas opções, como labels dos jogadores."},{"index":"2","when":"2026-08-03T16:00:53Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-028, T-032 e B-015 na worktree-1."},{"index":"3","when":"2026-08-04T17:40:09Z","kind":"prompt","author":"Marco Mendão","summary":"Verificar T-028 slider na tab texto; mover picker cor do texto para tab estilo."},{"index":"4","when":"2026-08-04T18:55:30Z","kind":"prompt","author":"Marco Mendão","summary":"Bug: caixa de selecção tracejada não acompanha o crescimento do texto no slider."},{"index":"5","when":"2026-08-04T19:00:27Z","kind":"feedback","author":"Marco Mendão","summary":"/commit-all — slider, cor na tab estilo, bounds de selecção."}],"commits":[{"sha":"d619847","repo":"coachid-taskmark","date":"2026-07-31T00:09:24+01:00","author":"Marco Mendão","message":"add T-028 text element size slider"},{"sha":"2553e5d","repo":"coachid_app_frontend","date":"2026-08-04T20:00:33+01:00","author":"Marco Mendão","message":"add text size slider and fix selection bounds"},{"sha":"a85edbe","repo":"coachid-taskmark","date":"2026-08-04T20:00:58+01:00","author":"Marco Mendão","message":"sync taskmark board for T-028"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T16:00:53Z","ended":"2026-08-04T12:00:00Z","summary":"auto-closed: idle cap (next-day 12:00 UTC)"},{"session":"2","actor":"Marco Mendão","started":"2026-08-04T17:40:09Z","ended":"2026-08-04T19:00:27Z","summary":"Slider tab Texto; cor do texto em Estilo; bounds de selecção com labelSize."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md":{"id":"S-005","title":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","type":"story","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":11,"actualMs":685000,"tags":["motor-exercicios","planeamento","categoria","fase-tipo","multi-select"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:12:08Z","completedAt":"2026-08-05T00:00:08Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md","userStory":"Como treinador, quero que o campo **Fase/Tipo** (planeamento, ao criar um treino) e o campo **Categoria** (motor de exercícios) partilhem a mesma lista de valores — com multi-selecção de categorias por exercício e listagem clara — para classificar treinos e exercícios de forma consistente.","acceptanceCriteria":[{"checked":true,"text":"O campo **Fase/Tipo** no planeamento (criar treino) usa a mesma lista/fonte que **Categoria** no módulo de exercícios"},{"checked":true,"text":"Os valores existentes de **Fase/Tipo** e **Categoria** são merged numa única lista (sem duplicados desnecessários)"},{"checked":true,"text":"A lista unificada inclui o novo valor **Jogo**"},{"checked":true,"text":"O valor **Outro** permanece sempre o último elemento da lista"},{"checked":true,"text":"Um exercício pode ter **mais do que uma** Categoria associada"},{"checked":true,"text":"Na listagem de exercícios, mostra-se apenas uma **Categoria**; se houver mais, aparece **+x** (x = número de categorias adicionais)"},{"checked":true,"text":"Em casos com **+x**, existe um tooltip que lista **todas** as categorias associadas ao exercício"}],"acceptanceCriteriaRaw":"- [x] O campo **Fase/Tipo** no planeamento (criar treino) usa a mesma lista/fonte que **Categoria** no módulo de exercícios\n- [x] Os valores existentes de **Fase/Tipo** e **Categoria** são merged numa única lista (sem duplicados desnecessários)\n- [x] A lista unificada inclui o novo valor **Jogo**\n- [x] O valor **Outro** permanece sempre o último elemento da lista\n- [x] Um exercício pode ter **mais do que uma** Categoria associada\n- [x] Na listagem de exercícios, mostra-se apenas uma **Categoria**; se houver mais, aparece **+x** (x = número de categorias adicionais)\n- [x] Em casos com **+x**, existe um tooltip que lista **todas** as categorias associadas ao exercício","tasksMarkdown":"- [T-032](items/T-032-categorias-renomear-remover-esquemas.md) — Categorias exercícios/treinos — remover Esquemas tácticos e renomear labels","children":[{"id":"T-032","title":"Categorias exercícios/treinos — remover Esquemas tácticos e renomear labels","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/items/T-032-categorias-renomear-remover-esquemas.md"}],"promptFeedback":[{"index":"2","when":"2026-07-28T07:12:08Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-005 completa."},{"index":"3","when":"2026-07-28T07:23:33Z","kind":"feedback","author":"Marco Mendão","summary":"S-005 delivered: shared list + multi category + +x tooltip."},{"index":"1","when":"2026-07-23T05:29:30Z","kind":"prompt","author":"Marco Mendão","summary":"Unificar Fase/Tipo (planeamento) com Categoria (exercícios); merge valores; acrescentar Jogo; Outro no fim; multi-categoria por exercício; listagem com +x e tooltip."}],"commits":[{"sha":"536a889","repo":"coachid-taskmark","date":"2026-07-31T00:23:10+01:00","author":"Marco Mendão","message":"add T-032 rename exercise categories"},{"sha":"23067ca","repo":"coachid_app_frontend","date":"2026-07-28T07:23:11Z","author":"Marco Mendão","message":"unify exercise categories and training phase multi-select"},{"sha":"efb7a81","repo":"coachid_app_api","date":"2026-07-28T07:23:11Z","author":"Marco Mendão","message":"unify phase-category list and exercise categories array"},{"sha":"6a4f376","repo":"coachid-taskmark","date":"2026-07-28T07:23:40Z","author":"Marco Mendão","message":"complete S-005 unify category phase-type"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:12:08Z","ended":"2026-07-28T07:23:33Z","summary":"Unified phase/category list, multi-select on exercises, +x list badges."},{"session":"2","actor":"Marco Mendão","started":"2026-08-05T00:00:08Z","ended":"2026-08-05T00:00:08Z","summary":"rollup: children done."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/items/T-032-categorias-renomear-remover-esquemas.md":{"id":"T-032","title":"Categorias exercícios/treinos — remover Esquemas tácticos e renomear labels","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":8,"actualMs":480000,"tags":["motor-exercicios","planeamento","categoria","i18n","labels"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-005","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T23:38:49Z","completedAt":"2026-08-04T23:59:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/items/T-032-categorias-renomear-remover-esquemas.md","description":"No selector de **categoria** dos exercícios/treinos (lista unificada S-005), aplicar:\n\n1. **Remover** «Esquemas tácticos»\n2. «Fase Técnica» → **«Técnica»**\n3. «Físico / Condição» → **«Condição física»**","acceptanceCriteria":[{"checked":true,"text":"A opção **Esquemas tácticos** deixa de aparecer no selector de categoria (exercícios e treinos / Fase-Tipo)"},{"checked":true,"text":"O label **Fase Técnica** passa a **Técnica** em todos os sítios que usam a lista unificada"},{"checked":true,"text":"O label **Físico / Condição** passa a **Condição física** nos mesmos sítios"},{"checked":true,"text":"Dados existentes com a categoria removida ou antigos labels continuam a comportar-se de forma segura (migração/map/display sem partir filtros nem listagens)"},{"checked":true,"text":"i18n (pt/en se aplicável) alinhado com os novos nomes"}],"acceptanceCriteriaRaw":"- [x] A opção **Esquemas tácticos** deixa de aparecer no selector de categoria (exercícios e treinos / Fase-Tipo)\n- [x] O label **Fase Técnica** passa a **Técnica** em todos os sítios que usam a lista unificada\n- [x] O label **Físico / Condição** passa a **Condição física** nos mesmos sítios\n- [x] Dados existentes com a categoria removida ou antigos labels continuam a comportar-se de forma segura (migração/map/display sem partir filtros nem listagens)\n- [x] i18n (pt/en se aplicável) alinhado com os novos nomes","reproSteps":"","fixCriteria":"","notes":"Lista partilhada categoria exercícios ↔ Fase/Tipo planeamento (S-005). Confirmar keys internas vs labels de UI.","promptFeedback":[{"index":"1","when":"2026-07-30T23:22:48Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — remover Esquemas tácticos; Fase Técnica→Técnica; Físico/Condição→Condição física."},{"index":"2","when":"2026-08-04T23:38:49Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-032 e B-015."},{"index":"3","when":"2026-08-04T23:59:54Z","kind":"feedback","author":"Marco Mendão","summary":"Verified done T-032: AC met in worktree-1."}],"commits":[{"sha":"536a889","repo":"coachid-taskmark","date":"2026-07-31T00:23:10+01:00","author":"Marco Mendão","message":"add T-032 rename exercise categories"},{"sha":"1020b7d","repo":"coachid_app_api","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"fix exercise media await and background save"},{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T23:38:49Z","ended":"2026-08-04T23:46:49Z","summary":"Categories rename/remove tactical_schemes. shared-batch: 8 of 21min by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md":{"id":"S-006","title":"Duplicar exercício com confirmação e sufixo (copia)","type":"story","status":"done","priority":"medium","size":"M","points":4,"estimateMinutes":20,"actualMinutes":18,"actualMs":1127000,"tags":["motor-exercicios","duplicate","modal"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-001","epic":"E-001","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:32:33Z","completedAt":"2026-08-05T00:00:08Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md","userStory":"Como utilizador do motor de exercícios, quero poder duplicar um exercício (com confirmação), para reutilizar um exercício existente sem o alterar; a cópia deve aparecer com o nome `<nome anterior> (copia)`.","acceptanceCriteria":[{"checked":true,"text":"Existe uma acção para duplicar um exercício"},{"checked":true,"text":"Ao duplicar, é mostrado um modal de confirmação antes de criar a cópia"},{"checked":true,"text":"Após confirmar, o exercício duplicado é criado com o nome `<nome anterior> (copia)`"},{"checked":true,"text":"O exercício original permanece inalterado"},{"checked":true,"text":"A cópia fica visível na listagem / contexto esperado após a duplicação"}],"acceptanceCriteriaRaw":"- [x] Existe uma acção para duplicar um exercício\n- [x] Ao duplicar, é mostrado um modal de confirmação antes de criar a cópia\n- [x] Após confirmar, o exercício duplicado é criado com o nome `<nome anterior> (copia)`\n- [x] O exercício original permanece inalterado\n- [x] A cópia fica visível na listagem / contexto esperado após a duplicação","tasksMarkdown":"- [B-015](items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md) — Duplicar exercício não regenera imagens/vídeos de preview\n- [T-049](items/T-049-spinner-loading-duplicar-exercicio.md) — Spinner de loading no botão duplicar exercício","children":[{"id":"B-015","title":"Duplicar exercício não regenera imagens/vídeos de preview","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md"},{"id":"T-049","title":"Spinner de loading no botão duplicar exercício","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/T-049-spinner-loading-duplicar-exercicio.md"}],"promptFeedback":[{"index":"4","when":"2026-08-04T23:53:46Z","kind":"prompt","author":"Marco Mendão","summary":"Spinner no botão duplicar enquanto a API responde (T-049)."},{"index":"3","when":"2026-07-28T07:36:26Z","kind":"feedback","author":"Marco Mendão","summary":"S-006 delivered."},{"index":"2","when":"2026-07-28T07:32:33Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-001 e S-006."},{"index":"1","when":"2026-07-23T05:32:13Z","kind":"prompt","author":"Marco Mendão","summary":"Permitir duplicar exercício; modal de confirmação; nome da cópia = nome anterior + \" (copia)\"."}],"commits":[{"sha":"2955ff4","repo":"coachid-taskmark","date":"2026-07-30T23:58:14+01:00","author":"Marco Mendão","message":"add B-015 duplicate exercise media regen"},{"sha":"884c04e","repo":"coachid_app_frontend","date":"2026-07-28T07:35:52Z","author":"Marco Mendão","message":"scale text labels 180% and add exercise duplicate"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:32:33Z","ended":"2026-07-28T07:34:53Z","summary":"Duplicate exercise with confirm modal and (copia) suffix. shared-batch: 140230 of 233717ms by points."},{"session":"2","actor":"Marco Mendão","started":"2026-08-05T00:00:08Z","ended":"2026-08-05T00:00:08Z","summary":"rollup: children done."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md":{"id":"B-015","title":"Duplicar exercício não regenera imagens/vídeos de preview","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":15,"actualMinutes":13,"actualMs":780000,"tags":["motor-exercicios","duplicate","media","preview","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-006","epic":"E-001","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T23:38:49Z","completedAt":"2026-08-04T23:59:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md","description":"Ao **duplicar** um exercício, as **imagens e vídeos de preview** do exercício original **não são copiados** para a cópia. Em vez de copiar ficheiros S3/media do original, após a duplicação devem ser **gerados de novo** os media do exercício (mesmo pipeline que na criação).","acceptanceCriteria":[{"checked":true,"text":"Após duplicar, a cópia **não depende** de copiar os ficheiros de media do exercício original"},{"checked":true,"text":"Após a duplicação, são **geradas novamente** as imagens de preview do exercício (ex.: green/white / superfície conforme o fluxo actual de create/save)"},{"checked":true,"text":"Se o exercício tem **animação/motion**: no momento da duplicação gera-se primeiro a **imagem**; o **vídeo** é gerado **assincronamente**, como já acontece ao **criar um exercício novo**"},{"checked":true,"text":"Preview da cópia fica utilizável na listagem e no editor após a regeneração (imagem imediata; vídeo quando o job assíncrono concluir)"},{"checked":true,"text":"No duplicate, a API **só responde** depois da thumbnail primary (green) existir; se falhar a geração, o create falha (UI não mostra exercício sem thumb)"}],"acceptanceCriteriaRaw":"- [x] Após duplicar, a cópia **não depende** de copiar os ficheiros de media do exercício original\n- [x] Após a duplicação, são **geradas novamente** as imagens de preview do exercício (ex.: green/white / superfície conforme o fluxo actual de create/save)\n- [x] Se o exercício tem **animação/motion**: no momento da duplicação gera-se primeiro a **imagem**; o **vídeo** é gerado **assincronamente**, como já acontece ao **criar um exercício novo**\n- [x] Preview da cópia fica utilizável na listagem e no editor após a regeneração (imagem imediata; vídeo quando o job assíncrono concluir)\n- [x] No duplicate, a API **só responde** depois da thumbnail primary (green) existir; se falhar a geração, o create falha (UI não mostra exercício sem thumb)","reproSteps":"1. Abrir um exercício que tenha preview de imagem (e, se aplicável, vídeo de animação).\n2. Duplicar o exercício (fluxo de confirmação / sufixo \"(copia)\").\n3. Abrir a cópia / listagem e observar o preview.\n4. Verificar que a imagem/vídeo de preview da cópia está em falta ou incorrecto (não regenerado).","fixCriteria":"- [x] Após duplicar, a cópia **não depende** de copiar os ficheiros de media do exercício original\n- [x] Após a duplicação, são **geradas novamente** as imagens de preview do exercício (ex.: green/white / superfície conforme o fluxo actual de create/save)\n- [x] Se o exercício tem **animação/motion**: no momento da duplicação gera-se primeiro a **imagem**; o **vídeo** é gerado **assincronamente**, como já acontece ao **criar um exercício novo**\n- [x] Preview da cópia fica utilizável na listagem e no editor após a regeneração (imagem imediata; vídeo quando o job assíncrono concluir)\n- [x] No duplicate, a API **só responde** depois da thumbnail primary (green) existir; se falhar a geração, o create falha (UI não mostra exercício sem thumb)","notes":"Alinhar com o pipeline de export/media usado no create (imagem síncrona + vídeo async para motion). Relacionado com S-006 (duplicar exercício).","promptFeedback":[{"index":"1","when":"2026-07-30T22:57:42Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — bug duplicar exercício: previews imagem/vídeo não copiados; regenerar após duplicação; com animação: imagem já + vídeo async como no create."},{"index":"2","when":"2026-08-04T23:38:49Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-032 e B-015."},{"index":"3","when":"2026-08-04T23:51:20Z","kind":"prompt","author":"Marco Mendão","summary":"Duplicate: thumbnail gerada antes da API largar o endpoint para a UI."},{"index":"4","when":"2026-08-04T23:59:54Z","kind":"feedback","author":"Marco Mendão","summary":"Verified done B-015: AC met in worktree-1."}],"commits":[{"sha":"2955ff4","repo":"coachid-taskmark","date":"2026-07-30T23:58:14+01:00","author":"Marco Mendão","message":"add B-015 duplicate exercise media regen"},{"sha":"1020b7d","repo":"coachid_app_api","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"fix exercise media await and background save"},{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"},{"sha":"d2bc24b","repo":"coachid-taskmark","date":"2026-08-04T23:58:30Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T23:38:49Z","ended":"2026-08-04T23:51:49Z","summary":"Duplicate await green preview + regen. shared-batch: 13 of 21min by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/T-049-spinner-loading-duplicar-exercicio.md":{"id":"T-049","title":"Spinner de loading no botão duplicar exercício","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":5,"actualMs":347000,"tags":["motor-exercicios","duplicate","modal","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-006","epic":"E-001","created":"2026-08-04","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-04T23:54:07Z","completedAt":"2026-08-04T23:59:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/T-049-spinner-loading-duplicar-exercicio.md","description":"No modal de confirmação de duplicar exercício, o botão de confirmar deve mostrar um spinner enquanto a API responde (get + create), para o utilizador perceber que a acção está em curso — especialmente relevante porque a duplicação pode esperar regeneração de preview.","acceptanceCriteria":[{"checked":true,"text":"Enquanto a duplicação está a decorrer, o botão de confirmar mostra um spinner"},{"checked":true,"text":"O botão fica desactivado durante o pedido (evita double-submit)"},{"checked":true,"text":"Após sucesso ou erro, o spinner desaparece e o botão volta ao estado normal"}],"acceptanceCriteriaRaw":"- [x] Enquanto a duplicação está a decorrer, o botão de confirmar mostra um spinner\n- [x] O botão fica desactivado durante o pedido (evita double-submit)\n- [x] Após sucesso ou erro, o spinner desaparece e o botão volta ao estado normal","reproSteps":"","fixCriteria":"","notes":"`isDuplicating` já existe em `ExercisesManageClient`; falta só o feedback visual (padrão `IconLoader2` + `animate-spin` como noutros dialogs).","promptFeedback":[{"index":"1","when":"2026-08-04T23:53:46Z","kind":"prompt","author":"Marco Mendão","summary":"O botão duplicar deve ter um loading (spinner) enquanto espera a resposta da API."},{"index":"2","when":"2026-08-04T23:59:54Z","kind":"feedback","author":"Marco Mendão","summary":"Verified done T-049: spinner in ExercisesManageClient."}],"commits":[{"sha":"5b5d30d","repo":"coachid_app_frontend","date":"2026-08-05T00:58:07+01:00","author":"Marco Mendão","message":"save exercises without client png upload"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-04T23:54:07Z","ended":"2026-08-04T23:59:54Z","summary":"Spinner on duplicate confirm button; disabled while pending."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/epic.md":{"id":"E-002","title":"PSE","type":"epic","status":"done","priority":"medium","size":"—","points":12,"estimateMinutes":1223,"actualMinutes":557,"actualMs":33427000,"tags":["module","pse"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T07:22:22Z","completedAt":"2026-07-29T16:54:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/epic.md","goal":"Entregar e evoluir o módulo PSE (Percepção Subjetiva de Esforço) — recolha, visualização e utilização de dados de esforço no CoachID.","scope":"- Modelos, APIs e UI de PSE\n- Integração com treinos e outros módulos quando necessário","outOfScope":"- Módulos Motor de exercícios, Wellness, Planeamento e Lineup (epics próprios)","successMetrics":"- Fluxos principais de PSE utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"S-003","title":"Timeline de eventos no estado de envio de emails de notificação","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md"},{"id":"B-001","title":"PSE salta para a primeira da semana após editar duração","type":"bug","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md"},{"id":"B-007","title":"Spam de emails PSE — cron reenvia sem onlyUnnotified e wipe de notifiedAt","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md"},{"id":"B-036","title":"PSE — skeleton em loop numa semana sem treinos","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md"},{"id":"T-003","title":"Selecção por defeito PSE — última da semana ou hoje","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md"},{"id":"T-006","title":"Auto-gerar nome ao criar PSE no planeamento (treino/jogo)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md"}],"commits":[{"sha":"3379a9f","repo":"coachid-taskmark","date":"2026-07-23T05:20:00Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T16:54:10Z","ended":"2026-07-29T16:54:10Z","summary":"rollup: all children done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md":{"id":"B-001","title":"PSE salta para a primeira da semana após editar duração","type":"bug","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":20,"actualMinutes":19,"actualMs":1161000,"tags":["pse","bug","navigation","session-duration"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T07:22:22Z","completedAt":"2026-07-23T07:41:43Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md","description":"Numa semana com múltiplos eventos PSE, após editar a duração da sessão num jogador na última PSE da lista, a alteração grava-se correctamente, mas a lista passa a mostrar a primeira PSE da semana. O dropdown superior continua a mostrar a sessão que foi editada — estado inconsistente entre lista e dropdown.","acceptanceCriteria":[{"checked":true,"text":"Após alterar a duração, o utilizador permanece na mesma PSE seleccionada"},{"checked":true,"text":"Lista da semana e dropdown superior mostram a mesma sessão"},{"checked":true,"text":"A alteração de duração continua a gravar-se correctamente"},{"checked":true,"text":"Comportamento verificado com vários eventos na mesma semana (incl. última da lista)"}],"acceptanceCriteriaRaw":"- [x] Após alterar a duração, o utilizador permanece na mesma PSE seleccionada\n- [x] Lista da semana e dropdown superior mostram a mesma sessão\n- [x] A alteração de duração continua a gravar-se correctamente\n- [x] Comportamento verificado com vários eventos na mesma semana (incl. última da lista)","reproSteps":"1. Abrir uma semana com múltiplos eventos de PSE\n2. Navegar até ao último PSE da lista dessa semana\n3. Clicar num jogador e alterar a duração da sessão\n4. Observar lista vs dropdown após a gravação","fixCriteria":"- [x] Após alterar a duração, o utilizador permanece na mesma PSE seleccionada\n- [x] Lista da semana e dropdown superior mostram a mesma sessão\n- [x] A alteração de duração continua a gravar-se correctamente\n- [x] Comportamento verificado com vários eventos na mesma semana (incl. última da lista)","notes":"Prioridade máxima (critical). General task no epic E-002 (sem user story).","promptFeedback":[{"index":"1","when":"2026-07-23T05:00:27Z","kind":"prompt","author":"Marco Mendão","summary":"Repro: semana multi-PSE → última → editar duração jogador → lista vai à 1ª, dropdown mantém editada. Esperado: permanecer na mesma PSE."},{"index":"2","when":"2026-07-23T05:05:02Z","kind":"feedback","author":"Marco Mendão","summary":"Remover associação a story; manter apenas no epic PSE."},{"index":"3","when":"2026-07-23T07:22:22Z","kind":"prompt","author":"Marco Mendão","summary":"Work on B-001 in worktree-1: fix PSE jumping to first after duration edit."},{"index":"4","when":"2026-07-23T07:41:43Z","kind":"feedback","author":"Marco Mendão","summary":"User confirmed B-001 solved; complete-work."}],"commits":[{"sha":"1952758","repo":"coachid_app_frontend","date":"2026-07-23T08:39:27+01:00","author":"Marco Mendão","message":"fix pse session selection after duration edit"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T07:22:22Z","ended":"2026-07-23T07:41:43Z","summary":"Shared selectedSessionId in RpesContext; stop dual SessionSelector overwrite after duration save; stabilize setSession by id"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md":{"id":"B-007","title":"Spam de emails PSE — cron reenvia sem onlyUnnotified e wipe de notifiedAt","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":156000,"tags":["pse","bug","email","notifications","sendgrid","cron"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T09:43:45Z","completedAt":"2026-07-23T09:46:21Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md","description":"Espelho PSE do [B-005](../../E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md) (Wellness, já feito). O cron PSE (`RpeNotificationJob`, `EVERY_5_MINUTES`) chama `notifyRPEAllPlayers(sessionId)` **sem** `{ onlyUnnotified: true }`, pelo que cada tick pode voltar a enviar a todos os jogadores elegíveis enquanto o companion não tiver `notifiedAt`.\n\nAlém disso, `createRpeArtifacts` / updates manuais fazem replace cego de `data` no companion `pse_report`, o que pode **apagar** `notifiedAt` / `notifyAttempts` / `notifyError` e rearmar o cron (mesmo padrão que Wellness antes do fix B-005).\n\nNota: ordenação/estado SMTP (`sending` timestamp −1, prioridade de evento) já foi aplicada a RPE no pacote B-005 — fora do scope mínimo deste bug, excepto regressões.","acceptanceCriteria":[{"checked":true,"text":"O cron PSE chama `notifyRPEAllPlayers` com `{ onlyUnnotified: true }`"},{"checked":true,"text":"`onlyUnnotified` trata como já notificado qualquer jogador com `events.length > 0` (e/ou sinal equivalente robusto se existir)"},{"checked":true,"text":"Updates a companions `pse_report` (**createRpeArtifacts**, manual reminder) **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`), excepto clear intencional ao reagendar para o futuro"},{"checked":true,"text":"Segundo tick do cron (e recreate de companion com `notifiedAt` preservado) resulta em `sent=0` / skip para jogadores já com eventos — verificado por teste"},{"checked":true,"text":"Sem regressão no badge SMTP PSE (util partilhado de B-005)"}],"acceptanceCriteriaRaw":"- [x] O cron PSE chama `notifyRPEAllPlayers` com `{ onlyUnnotified: true }`\n- [x] `onlyUnnotified` trata como já notificado qualquer jogador com `events.length > 0` (e/ou sinal equivalente robusto se existir)\n- [x] Updates a companions `pse_report` (**createRpeArtifacts**, manual reminder) **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`), excepto clear intencional ao reagendar para o futuro\n- [x] Segundo tick do cron (e recreate de companion com `notifiedAt` preservado) resulta em `sent=0` / skip para jogadores já com eventos — verificado por teste\n- [x] Sem regressão no badge SMTP PSE (util partilhado de B-005)","reproSteps":"1. Sessão PSE com companion `pse_report` devido (`dateTime` passado, sem `notifiedAt` ou após wipe).\n2. Observar logs `Dispatching RPE reminders` / `notifyRPEAllPlayers` com `mode=all` e `sent>0` em ticks sucessivos, ou após editar o treino/jogo fonte (recreate companion).\n3. No Mongo: companion `otherType: pse_report` — `notifiedAt` ausente após update de appointment; nos `rpe.stats[].events` múltiplos pares `sending`→`processed` no mesmo jogador/sessão.","fixCriteria":"- [x] O cron PSE chama `notifyRPEAllPlayers` com `{ onlyUnnotified: true }`\n- [x] `onlyUnnotified` trata como já notificado qualquer jogador com `events.length > 0` (e/ou sinal equivalente robusto se existir)\n- [x] Updates a companions `pse_report` (**createRpeArtifacts**, manual reminder) **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`), excepto clear intencional ao reagendar para o futuro\n- [x] Segundo tick do cron (e recreate de companion com `notifiedAt` preservado) resulta em `sent=0` / skip para jogadores já com eventos — verificado por teste\n- [x] Sem regressão no badge SMTP PSE (util partilhado de B-005)","notes":"Prioridade **high** — mesmo risco de spam/reputação SendGrid que B-005; o relatório original misturava RPE/Wellness, mas o spam confirmado foi Wellness; este item fecha o buraco PSE.\n\nFicheiros-chave (worktree-1):\n\n- `coachid_app_api/src/rpe/rpe-notification.job.ts`\n- `coachid_app_api/src/rpe/rpe.service.comumnication.ts`\n- `coachid_app_api/src/rpe/pse-automation.service.ts`\n\nRelacionado: B-005 (Wellness). ID **B-007** (B-006 já usado em fotos jogadores / E-009).\n\nGeneral task no epic E-002 (sem user story).","promptFeedback":[{"index":"1","when":"2026-07-23T09:34:08Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar ao epic PSE o bug espelho do spam Wellness (B-005); pedido como B-006 — alocado B-007 porque B-006 já existe."},{"index":"2","when":"2026-07-23T09:43:45Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-007 na worktree-1."},{"index":"3","when":"2026-07-23T09:46:21Z","kind":"feedback","author":"Marco Mendão","summary":"Fix em worktree-1: cron `onlyUnnotified`, merge notify fields em companions, testes OK."}],"commits":[{"sha":"0f8d366","repo":"coachid-taskmark","date":"2026-07-23T10:43:10+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"646a535","repo":"coachid_app_api","date":"2026-07-23T10:46:21+01:00","author":"Marco Mendão","message":"fix pse email spam cron and companion notifiedAt wipe"},{"sha":"a26c3b1","repo":"coachid-taskmark","date":"2026-07-23T10:46:56+01:00","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T09:43:45Z","ended":"2026-07-23T09:46:21Z","summary":"Cron onlyUnnotified; mergePreservedNotifyFields em createRpeArtifacts/manual; testes job/automation/comumnication."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md":{"id":"B-036","title":"PSE — skeleton em loop numa semana sem treinos","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":78,"actualMinutes":1,"actualMs":88000,"tags":["pse","rpe","loading","empty-state"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:19:12Z","completedAt":"2026-08-11T16:20:40Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md","description":"Ao abrir a PSE numa semana sem treinos/jogos, o esqueleto (loading) fica indefinidamente em vez de mostrar o empty state.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"1. Ir a PSE\n2. Seleccionar uma semana sem treinos nem jogos\n3. Observar a tabela / conteúdo","fixCriteria":"","notes":"Causa: `session` no contexto arranca como `undefined` (loading). Com lista vazia, `setSession` fazia `prev == null ? prev : null`, o que **preservava `undefined`** (`undefined == null` é true) e a tabela ficava em `RpesTableSkeleton`.\n\nFix: sem `selectedSessionId`, se `data` está vazio → `null` (empty state); se ainda há sessões → `undefined` (skeleton até ao auto-select).","promptFeedback":[{"index":"1","when":"2026-08-11T16:19:12Z","kind":"prompt","author":"Marco Mendão","summary":"Bug PSE: semana sem treinos — skeleton em loop em vez de empty state"}],"commits":[{"sha":"fa35238","repo":"coachid_app_frontend","date":"2026-08-11T16:23:12Z","author":"Marco Mendão","message":"fix pse empty week skeleton loop"},{"sha":"2a8c5ed","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-11T16:23:12Z","author":"Marco Mendão","message":"fix pse empty week skeleton loop"},{"sha":"097b0d2","repo":"coachid-taskmark","date":"2026-08-11T16:23:13Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:19:12Z","ended":"2026-08-11T16:20:40Z","summary":"Fix SessionSelector: empty week settles session to null instead of preserving undefined"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md":{"id":"T-003","title":"Selecção por defeito PSE — última da semana ou hoje","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":45,"actualMinutes":49,"actualMs":2944000,"tags":["pse","ui","default-selection","today"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T16:27:00Z","completedAt":"2026-07-23T17:17:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md","description":"Ao abrir uma semana de PSE, a sessão seleccionada por defeito deve ser a **última PSE** dessa semana. Se o utilizador abrir a **semana actual**, a PSE por defeito deve ser a do **dia de hoje**, com um elemento distintivo que indique claramente que é hoje.","acceptanceCriteria":[{"checked":true,"text":"Ao abrir uma semana (não actual), a PSE seleccionada por defeito é a última da lista dessa semana"},{"checked":true,"text":"Ao abrir a semana actual, a PSE seleccionada por defeito é a do dia de hoje"},{"checked":true,"text":"Na semana actual, se não houver PSE hoje, seleccionar a PSE mais recente já passada dessa semana"},{"checked":true,"text":"Existe um elemento visual distintivo que marca o dia de hoje"},{"checked":true,"text":"Comportamento consistente com dropdown e lista da semana"},{"checked":true,"text":"Listagem de sessões PSE ordenada por data (ascendente)"},{"checked":true,"text":"Parsing de datas de treino aceita yyyy-MM-dd (API) além de yyyy/MM/dd"},{"checked":true,"text":"Wellness (entrada /nav/tabs) usa a mesma regra de dia por defeito na semana actual"},{"checked":true,"text":"A regra de defeito ignora respostas já preenchidas (só data da sessão)"}],"acceptanceCriteriaRaw":"- [x] Ao abrir uma semana (não actual), a PSE seleccionada por defeito é a última da lista dessa semana\n- [x] Ao abrir a semana actual, a PSE seleccionada por defeito é a do dia de hoje\n- [x] Na semana actual, se não houver PSE hoje, seleccionar a PSE mais recente já passada dessa semana\n- [x] Existe um elemento visual distintivo que marca o dia de hoje\n- [x] Comportamento consistente com dropdown e lista da semana\n- [x] Listagem de sessões PSE ordenada por data (ascendente)\n- [x] Parsing de datas de treino aceita yyyy-MM-dd (API) além de yyyy/MM/dd\n- [x] Wellness (entrada /nav/tabs) usa a mesma regra de dia por defeito na semana actual\n- [x] A regra de defeito ignora respostas já preenchidas (só data da sessão)","reproSteps":"","fixCriteria":"","notes":"Relacionado com B-001. General task no epic E-002 (sem user story).","promptFeedback":[{"index":"1","when":"2026-07-23T05:00:27Z","kind":"prompt","author":"Marco Mendão","summary":"Default ao abrir semana = última PSE; semana actual = hoje com distintivo visual."},{"index":"2","when":"2026-07-23T05:05:02Z","kind":"feedback","author":"Marco Mendão","summary":"Remover associação a story; manter apenas no epic PSE."},{"index":"3","when":"2026-07-23T16:27:00Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-003, T-006, T-007."},{"index":"4","when":"2026-07-23T16:32:53Z","kind":"feedback","author":"Marco Mendão","summary":"SessionSelector: última da semana / hoje na semana actual + badge Hoje."},{"index":"5","when":"2026-07-23T17:07:37Z","kind":"prompt","author":"Marco Mendão","summary":"Semana actual sem PSE hoje: seleccionar PSE mais próxima já passada (ex. 23 e 25, hoje 24 → 23)."},{"index":"6","when":"2026-07-23T17:10:21Z","kind":"feedback","author":"Marco Mendão","summary":"Sem PSE hoje → última passada da semana; só futuras → primeira a vir."},{"index":"7","when":"2026-07-23T17:17:15Z","kind":"prompt","author":"Marco Mendão","summary":"Bug: 21/22/24/26 hoje 23 → mostrava 26; fix parse yyyy-MM-dd; ordenar por data; mesma regra no wellness."},{"index":"8","when":"2026-07-23T17:17:30Z","kind":"feedback","author":"Marco Mendão","summary":"Causa: parse yyyy/MM/dd falhava em datas API yyyy-MM-dd → caía na última; fix + sort + wellness."}],"commits":[{"sha":"e7cc1bb","repo":"coachid_app_frontend","date":"2026-07-23T17:17:15Z","author":"Marco Mendão","message":"fix pse default date parse sort and wellness day"},{"sha":"824da8d","repo":"coachid_app_frontend","date":"2026-07-23T17:07:37Z","author":"Marco Mendão","message":"prefer latest past pse when today has none"},{"sha":"7af9580","repo":"coachid_app_frontend","date":"2026-07-23T16:33:23Z","author":"Marco Mendão","message":"default pse session today and auto-name planning reminders"},{"sha":"9997ba5","repo":"coachid_app_api","date":"2026-07-23T16:33:24Z","author":"Marco Mendão","message":"accept source session on wellness planning reminder"},{"sha":"1616a03","repo":"coachid-taskmark","date":"2026-07-23T17:33:39Z","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"664e16b","repo":"coachid-taskmark","date":"2026-07-23T18:07:47Z","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"e851884","repo":"coachid-taskmark","date":"2026-07-23T18:17:30Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T16:27:00Z","ended":"2026-07-23T16:28:57Z","summary":"shared-batch: 117738 of 353213ms by points — default sessão PSE última/hoje + badge"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T17:07:21Z","ended":"2026-07-23T17:10:21Z","summary":"Fallback semana actual: PSE mais recente já passada (senão próxima futura)"},{"session":"3","actor":"Marco Mendão","started":"2026-07-23T16:27:00Z","ended":"2026-07-23T17:07:37Z","summary":"auto-recovered: commit span"},{"session":"4","actor":"Marco Mendão","started":"2026-07-23T17:14:00Z","ended":"2026-07-23T17:17:30Z","summary":"Fix parse API dates, sort by date, wellness default rule"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md":{"id":"T-006","title":"Auto-gerar nome ao criar PSE no planeamento (treino/jogo)","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"tags":["pse","planeamento","naming","auto-generate"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T16:27:00Z","completedAt":"2026-07-23T16:32:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md","description":"Quando o utilizador cria um PSE **directamente no planeamento** ao seleccionar um **treino** ou um **jogo**, o nome do PSE deve ser **auto-gerado**. O campo continua **editável**, mas o valor inicial deve usar a **mesma regra de nomes** que já é usada quando o PSE é gerado automaticamente pela criação de um treino.","acceptanceCriteria":[{"checked":true,"text":"Ao criar PSE no planeamento ligado a um treino, o nome é preenchido automaticamente"},{"checked":true,"text":"Ao criar PSE no planeamento ligado a um jogo, o nome é preenchido automaticamente"},{"checked":true,"text":"O nome gerado segue a mesma convenção/formato dos PSE criados automaticamente com a criação de um treino"},{"checked":true,"text":"O utilizador pode editar o nome após a geração automática"},{"checked":true,"text":"Se o utilizador alterar treino/jogo seleccionado, o nome auto-gerado actualiza-se de forma coerente (salvo se o utilizador já o tiver personalizado — se aplicável documentar o comportamento escolhido)"}],"acceptanceCriteriaRaw":"- [x] Ao criar PSE no planeamento ligado a um treino, o nome é preenchido automaticamente\n- [x] Ao criar PSE no planeamento ligado a um jogo, o nome é preenchido automaticamente\n- [x] O nome gerado segue a mesma convenção/formato dos PSE criados automaticamente com a criação de um treino\n- [x] O utilizador pode editar o nome após a geração automática\n- [x] Se o utilizador alterar treino/jogo seleccionado, o nome auto-gerado actualiza-se de forma coerente (salvo se o utilizador já o tiver personalizado — se aplicável documentar o comportamento escolhido)","reproSteps":"","fixCriteria":"","notes":"General task no epic E-002. Espelho wellness: T-007.\n\nComportamento dirty: depois de editar o nome, mudanças de sessão **não** sobrescrevem o valor personalizado.","promptFeedback":[{"index":"1","when":"2026-07-23T05:55:36Z","kind":"prompt","author":"Marco Mendão","summary":"Criar PSE no planeamento (treino/jogo): auto-gerar nome (editável), igual ao naming do PSE auto da criação de treino."},{"index":"2","when":"2026-07-23T16:27:00Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-003, T-006, T-007."},{"index":"3","when":"2026-07-23T16:32:53Z","kind":"feedback","author":"Marco Mendão","summary":"Auto-nome PSE report (Training/adversary); dirty lock após edição."}],"commits":[{"sha":"7af9580","repo":"coachid_app_frontend","date":"2026-07-23T16:33:23Z","author":"Marco Mendão","message":"default pse session today and auto-name planning reminders"},{"sha":"9997ba5","repo":"coachid_app_api","date":"2026-07-23T16:33:24Z","author":"Marco Mendão","message":"accept source session on wellness planning reminder"},{"sha":"1616a03","repo":"coachid-taskmark","date":"2026-07-23T17:33:39Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T16:27:00Z","ended":"2026-07-23T16:28:57Z","summary":"shared-batch: 117738 of 353213ms by points — auto-nome PSE planeamento"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md":{"id":"S-003","title":"Timeline de eventos no estado de envio de emails de notificação","type":"story","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":482,"actualMs":28961000,"tags":["pse","ui","email","notifications"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-002","epic":"E-002","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T10:12:41Z","completedAt":"2026-07-23T10:15:03Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md","userStory":"Como treinador, quero ver uma timeline dos eventos de envio de email ao passar o rato sobre o estado do envio das notificações PSE, para perceber com detalhe o que aconteceu no envio para o utilizador.","acceptanceCriteria":[{"checked":true,"text":"Ao fazer hover sobre o estado de envio de uma notificação por email, aparece uma timeline com os eventos colectados desse envio"},{"checked":true,"text":"Por defeito a timeline mostra apenas os 4 eventos mais recentes"},{"checked":true,"text":"Se existirem mais de 4 eventos, mostra apenas os 4 mais recentes e um botão ver mais por baixo (sem 5.o desfocado)"},{"checked":true,"text":"Ao clicar no botão “ver mais”, abre-se uma vista (tabela) com todos os eventos registados"},{"checked":true,"text":"A tabela / timeline usa o util partilhado de ordenação ([T-011](../../../E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md) / `sortEmailEventsDescending`): `timestamp` → prioridade lifecycle → `reiceivedAt`; mais recente primeiro"},{"checked":true,"text":"Com 4 ou menos eventos, não se mostra o botão ver mais"}],"acceptanceCriteriaRaw":"- [x] Ao fazer hover sobre o estado de envio de uma notificação por email, aparece uma timeline com os eventos colectados desse envio\n- [x] Por defeito a timeline mostra apenas os 4 eventos mais recentes\n- [x] Se existirem mais de 4 eventos, mostra apenas os 4 mais recentes e um botão ver mais por baixo (sem 5.o desfocado)\n- [x] Ao clicar no botão “ver mais”, abre-se uma vista (tabela) com todos os eventos registados\n- [x] A tabela / timeline usa o util partilhado de ordenação ([T-011](../../../E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md) / `sortEmailEventsDescending`): `timestamp` → prioridade lifecycle → `reiceivedAt`; mais recente primeiro\n- [x] Com 4 ou menos eventos, não se mostra o botão ver mais","tasksMarkdown":"Implementado via `EmailEventsTimelineHover` partilhado + `RpesTableSendButton` (worktree-1).","children":[],"promptFeedback":[{"index":"1","when":"2026-07-23T05:03:07Z","kind":"prompt","author":"Marco Mendão","summary":"Story PSE+Wellness: hover no estado de envio de emails → timeline dos eventos; 4 visíveis + 5.º desfocado com “ver mais”; clique abre tabela completa ordenada por data (recente primeiro)."},{"index":"2","when":"2026-07-23T08:03:26Z","kind":"prompt","author":"Marco Mendão","summary":"Alinhar ordenação da timeline com o fix de timestamps empatados no B-005 (reiceivedAt + prioridade de evento)."},{"index":"3","when":"2026-07-23T10:12:41Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-003 e S-004."},{"index":"4","when":"2026-07-23T10:15:03Z","kind":"feedback","author":"Marco Mendão","summary":"Timeline partilhada + wiring PSE; ordenação T-011."},{"index":"5","when":"2026-07-23T10:42:48Z","kind":"feedback","author":"Marco Mendão","summary":"Fix flicker hover timeline: sem onFocus/onBlur, modal=false, onCloseAutoFocus preventDefault."},{"index":"6","when":"2026-07-23T17:27:25Z","kind":"prompt","author":"Marco Mendão","summary":"Sem 5.o desfocado: so 4 eventos + botao ver mais por baixo."},{"index":"7","when":"2026-07-23T17:27:25Z","kind":"feedback","author":"Marco Mendão","summary":"Preview: 4 linhas nitidas; overflow -> ver mais abaixo."}],"commits":[{"sha":"049c8e7","repo":"coachid_app_frontend","date":"2026-07-23T18:27:13Z","author":"Marco Mendão","message":"show four timeline events without blurred fifth"},{"sha":"c08094f","repo":"coachid_app_frontend","date":"2026-07-23T11:42:58+01:00","author":"Marco Mendão","message":"fix email timeline hover flicker on mouse leave"},{"sha":"cb54d5e","repo":"coachid_app_frontend","date":"2026-07-23T11:28:11+01:00","author":"Marco Mendão","message":"add email events timeline on pse and wellness send status"},{"sha":"6d6aba6","repo":"coachid-taskmark","date":"2026-07-23T11:28:11+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"f4907eb","repo":"coachid-taskmark","date":"2026-07-23T18:27:14Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T10:12:41Z","ended":"2026-07-23T10:13:52Z","summary":"shared-batch: 71 of 142s by points — EmailEventsTimelineHover + RpesTableSendButton"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T10:12:41Z","ended":"2026-07-23T18:27:13Z","summary":"auto-recovered: commit span"},{"session":"3","actor":"Marco Mendão","started":"2026-07-23T17:24:25Z","ended":"2026-07-23T17:25:55Z","summary":"shared-batch: 90000 of 180000ms by points — preview 4 + ver mais, sem blur"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/epic.md":{"id":"E-003","title":"Wellness","type":"epic","status":"done","priority":"medium","size":"—","points":8,"estimateMinutes":685,"actualMinutes":562,"actualMs":33743000,"tags":["module","wellness"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T08:14:42Z","completedAt":"2026-07-29T16:54:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/epic.md","goal":"Entregar e evoluir o módulo Wellness — questionários, indicadores de bem-estar e acompanhamento de atletas no CoachID.","scope":"- Modelos, APIs e UI de wellness\n- Integração com outros módulos do produto quando necessário","outOfScope":"- Módulos Motor de exercícios, PSE, Planeamento e Lineup (epics próprios)","successMetrics":"- Fluxos principais de wellness utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"S-004","title":"Timeline de eventos no estado de envio de emails de notificação","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md"},{"id":"B-005","title":"Spam de emails Wellness — cron reenvia apesar de estado Processado","type":"bug","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md"},{"id":"B-010","title":"Wellness manual no planeamento exige treino/jogo","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md"},{"id":"T-007","title":"Auto-gerar nome ao criar Wellness no planeamento (treino/jogo)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md"}],"commits":[{"sha":"bf3e30f","repo":"coachid_app_api","date":"2026-07-23T10:31:55+01:00","author":"Marco Mendão","message":"fix wellness email spam and smtp sending timestamps"},{"sha":"de8e84c","repo":"coachid_app_frontend","date":"2026-07-23T10:31:56+01:00","author":"Marco Mendão","message":"fix smtp event ordering and admin ticket stats resilience"},{"sha":"a82acdd","repo":"coachid_app_frontend","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"fix wellness day reminder without session"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T08:14:42Z","ended":"2026-07-23T09:31:56Z","summary":"auto-recovered: commit span"},{"session":"2","actor":"Marco Mendão","started":"2026-07-29T16:54:10Z","ended":"2026-07-29T16:54:10Z","summary":"rollup: all children done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md":{"id":"B-005","title":"Spam de emails Wellness — cron reenvia apesar de estado Processado","type":"bug","status":"done","priority":"critical","size":"XS","points":1,"estimateMinutes":75,"actualMinutes":75,"actualMs":4519000,"tags":["wellness","bug","email","notifications","sendgrid","cron","critical","smtp","ui"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-003","epic":"E-003","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T08:14:42Z","completedAt":"2026-07-23T09:30:01Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md","description":"Alguns clientes reportam emails de Wellness repetidos (percepcionados como ~de hora a hora). Na listagem, o estado de envio mostra **Processado** (evento SendGrid `processed` via webhook).\n\nO badge Processado confirma que o SendGrid **aceitou** o email — o sistema **não** está à espera do webhook para decidir retries. O stamp de “já notifiquei” vive no companion `wellness_reminder` (`data.notifiedAt` / `data.notifyAttempts`). O cron actual é `EVERY_5_MINUTES` (`WellnessReminderJob`); o job legado `EVERY_HOUR` em `wellness.job.ts` está comentado (confirmar se produção já tem este código).\n\nInvestigação (código `coachid_app_api`):\n\n1. **Vários companions por dia** — cada treino/jogo cria um `wellness_reminder`; N sessões no mesmo dia → N companions a disparar para o mesmo `(team, season, day)`. Com réplicas da API em paralelo, `onlyUnnotified` pode ser contornado antes do `$push` de `sending`.\n2. **`notifiedAt` apagado** — `createCompanion` / updates manuais fazem replace de `data` sem preservar `notifiedAt` / `notifyAttempts`, rearmando o companion.\n3. **`onlyUnnotified` frágil** — só verifica `Array.isArray(events) && events.length > 0`; ignora `notified: true`. Schema `events` está como `type: Object` (não array). Sem índice único em `(team, season, player, date)`, documentos duplicados sem `events` são reenviados enquanto outro mostra Processado.\n4. **Day com TZ do servidor** — `format(parseISO(companion.data.dateTime), 'yyyy/MM/dd')` usa o timezone do processo, não o da equipa/appointment. Em UTC, reminders de madrugada em Lisboa podem cair no dia errado; se o `dateTime` for recalculado e o `day` saltar, criam-se rows novas sem `events` → novo envio.\n\n### Problema relacionado — timestamps empatados (badge / timeline)\n\nEm muitos envios, `sending`, `processed` e `delivered` partilham o **mesmo** `timestamp` Unix (segundos). O frontend (`getSmtpStatus` / `SmtpStatusBadge`) ordena só por `timestamp` e usa o último — assunção incorrecta de que os eventos SG têm timestamp maior. Com empate, a ordem do array decide o badge: no exemplo real `sending` → `delivered` → `processed`, o badge fica **Processado** apesar de existir `delivered`. O PSE/RPE usa o mesmo padrão (`rpe.service.comumnication.ts` + `smtpStatus.ts`).\n\nIsto **não** causa o spam por si (o spam é cron/companions), mas explica badges enganadores (“Processado” em vez de “Entregue”) e ordenação incorrecta na timeline (S-003 / S-004). Resolver no mesmo pacote: util partilhado de ordenação/estado + prevenção no `sending`.\n\nRelacionado: espelho PSE criado como [B-007](../../E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md) (cron sem `onlyUnnotified` + wipe `notifiedAt`).","acceptanceCriteria":[{"checked":true,"text":"Jogadores com `notified: true` **ou** qualquer evento de envio (`sending` / `processed` / `delivered` / …) **não** voltam a receber email no dispatch automático"},{"checked":true,"text":"Updates a companions `wellness_reminder` **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`)"},{"checked":true,"text":"O `day` do dispatch é calculado no timezone do appointment/equipa (`formatInTimeZone`), não com `format()` local do servidor"},{"checked":true,"text":"No máximo **um** dispatch efectivo por `(team, season, day)` por ciclo (dedupe entre vários companions da mesma janela)"},{"checked":true,"text":"Schema `events` como array; preferir índice único em wellness `(team, season, player, date)` (ou equivalência que impeça duplicados)"},{"checked":true,"text":"Com badge de envio bem-sucedido na UI (`processed` / `delivered` / …), um segundo tick do cron (e um segundo companion do mesmo dia) resulta em `sent=0` / skip — verificado por teste"},{"checked":true,"text":"Confirmar em produção que o job legado `EVERY_HOUR` (`WellnessJob.handleNotifyWellnessesForDay`) permanece desactivado"},{"checked":true,"text":"`getSmtpStatus` / `SmtpStatusBadge` (e util partilhado) escolhem o estado por **prioridade de evento** quando os timestamps empatam — com `sending`+`delivered`+`processed` no mesmo segundo, o badge é **delivered** (não processed nem sending)"},{"checked":true,"text":"Ordenação de eventos para UI/timeline: `reiceivedAt` (ms) se existir, senão `timestamp * 1000`; em empate, prioridade do tipo; índice no array só como último recurso"},{"checked":true,"text":"Ao gravar o marcador interno `sending` (Wellness **e** RPE/PSE), o timestamp fica **antes** dos eventos SendGrid do mesmo segundo (ex. `Math.floor(Date.now()/1000) - 1` e/ou `reiceivedAt` em ms)"},{"checked":true,"text":"Testes unitários cobrem o payload real com timestamps iguais → estado `delivered` e ordem cronológica correcta na timeline"},{"checked":true,"text":"PSE/RPE beneficia do mesmo util (sem regressão no badge)"}],"acceptanceCriteriaRaw":"### Spam / cron (causa raiz)\n\n- [x] Jogadores com `notified: true` **ou** qualquer evento de envio (`sending` / `processed` / `delivered` / …) **não** voltam a receber email no dispatch automático\n- [x] Updates a companions `wellness_reminder` **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`)\n- [x] O `day` do dispatch é calculado no timezone do appointment/equipa (`formatInTimeZone`), não com `format()` local do servidor\n- [x] No máximo **um** dispatch efectivo por `(team, season, day)` por ciclo (dedupe entre vários companions da mesma janela)\n- [x] Schema `events` como array; preferir índice único em wellness `(team, season, player, date)` (ou equivalência que impeça duplicados)\n- [x] Com badge de envio bem-sucedido na UI (`processed` / `delivered` / …), um segundo tick do cron (e um segundo companion do mesmo dia) resulta em `sent=0` / skip — verificado por teste\n- [x] Confirmar em produção que o job legado `EVERY_HOUR` (`WellnessJob.handleNotifyWellnessesForDay`) permanece desactivado\n\n### Estado SMTP / ordenação (mesmo pacote)\n\n- [x] `getSmtpStatus` / `SmtpStatusBadge` (e util partilhado) escolhem o estado por **prioridade de evento** quando os timestamps empatam — com `sending`+`delivered`+`processed` no mesmo segundo, o badge é **delivered** (não processed nem sending)\n- [x] Ordenação de eventos para UI/timeline: `reiceivedAt` (ms) se existir, senão `timestamp * 1000`; em empate, prioridade do tipo; índice no array só como último recurso\n- [x] Ao gravar o marcador interno `sending` (Wellness **e** RPE/PSE), o timestamp fica **antes** dos eventos SendGrid do mesmo segundo (ex. `Math.floor(Date.now()/1000) - 1` e/ou `reiceivedAt` em ms)\n- [x] Testes unitários cobrem o payload real com timestamps iguais → estado `delivered` e ordem cronológica correcta na timeline\n- [x] PSE/RPE beneficia do mesmo util (sem regressão no badge)","reproSteps":"1. Equipas afectadas: listagem Wellness do dia com badge **Processado** no(s) jogador(es).\n2. Confirmar com o cliente quantos emails iguais chegaram e com que intervalo.\n3. No Mongo, para o dia/equipa:\n - Contar companions `type: other`, `data.otherType: wellness_reminder` com o mesmo dia efectivo (`dateTime` / `wellnessDay`); ver `notifiedAt` e `notifyAttempts`.\n - Nos `wellnesses` do jogador/dia: `events` (pares `sending`→`processed`/`delivered` com o **mesmo** `timestamp`), `notified`, e se existem **duplicados** `(team, season, player, date)`.\n4. Nos logs da API: linhas `Dispatching wellness reminders` / `notifyWellnessesAllForDay` com `sent>0` repetido para o mesmo day após Processado.\n5. (Badge) Com events `[sending, delivered, processed]` e o mesmo `timestamp`, a UI deve passar a mostrar **Entregue**, não Processado / Sending.","fixCriteria":"### Spam / cron (causa raiz)\n\n- [x] Jogadores com `notified: true` **ou** qualquer evento de envio (`sending` / `processed` / `delivered` / …) **não** voltam a receber email no dispatch automático\n- [x] Updates a companions `wellness_reminder` **preservam** `notifiedAt`, `notifyAttempts` e `notifyError` (merge; nunca replace cego de `data`)\n- [x] O `day` do dispatch é calculado no timezone do appointment/equipa (`formatInTimeZone`), não com `format()` local do servidor\n- [x] No máximo **um** dispatch efectivo por `(team, season, day)` por ciclo (dedupe entre vários companions da mesma janela)\n- [x] Schema `events` como array; preferir índice único em wellness `(team, season, player, date)` (ou equivalência que impeça duplicados)\n- [x] Com badge de envio bem-sucedido na UI (`processed` / `delivered` / …), um segundo tick do cron (e um segundo companion do mesmo dia) resulta em `sent=0` / skip — verificado por teste\n- [x] Confirmar em produção que o job legado `EVERY_HOUR` (`WellnessJob.handleNotifyWellnessesForDay`) permanece desactivado\n\n### Estado SMTP / ordenação (mesmo pacote)\n\n- [x] `getSmtpStatus` / `SmtpStatusBadge` (e util partilhado) escolhem o estado por **prioridade de evento** quando os timestamps empatam — com `sending`+`delivered`+`processed` no mesmo segundo, o badge é **delivered** (não processed nem sending)\n- [x] Ordenação de eventos para UI/timeline: `reiceivedAt` (ms) se existir, senão `timestamp * 1000`; em empate, prioridade do tipo; índice no array só como último recurso\n- [x] Ao gravar o marcador interno `sending` (Wellness **e** RPE/PSE), o timestamp fica **antes** dos eventos SendGrid do mesmo segundo (ex. `Math.floor(Date.now()/1000) - 1` e/ou `reiceivedAt` em ms)\n- [x] Testes unitários cobrem o payload real com timestamps iguais → estado `delivered` e ordem cronológica correcta na timeline\n- [x] PSE/RPE beneficia do mesmo util (sem regressão no badge)","notes":"Prioridade **critical** — spam a atletas / reputação SendGrid / confiança no produto.\n\nSize **L** — scope alargado: fix de cron + ordenação/estado SMTP partilhado (frontend + API Wellness/RPE).\n\nStories dependentes (reutilizar sort): [S-003](../stories/S-003-timeline-eventos-envio-email-notificacoes/story.md) (PSE), [S-004](../stories/S-004-timeline-eventos-envio-email-notificacoes/story.md) (Wellness).\n\nFicheiros-chave:\n\n- `coachid_app_api/src/wellness/wellness-reminder.job.ts`\n- `coachid_app_api/src/wellness/wellness.service.commuincations.ts`\n- `coachid_app_api/src/wellness/wellness-automation.service.ts`\n- `coachid_app_api/src/database/schemas/wellness.schema.ts`\n- `coachid_app_api/src/smtp/smtp.controller.ts` (webhook → `processed`)\n- `coachid_app_api/src/rpe/rpe.service.comumnication.ts` (`sending`)\n- `coachid_app_frontend/src/components/commons/smtpStatus.ts`\n- `coachid_app_frontend/src/components/commons/SmtpStatusBadge.tsx`\n\nGeneral task no epic E-003 (sem user story).","promptFeedback":[{"index":"1","when":"2026-07-23T07:30:00Z","kind":"prompt","author":"Marco Mendão","summary":"Clientes a receber RPE/wellness ~1h; UI mostra Processado; suspeita retry sem feedback SendGrid."},{"index":"2","when":"2026-07-23T07:44:00Z","kind":"feedback","author":"Marco Mendão","summary":"Confirmado: o spam reportado é de **Wellness** (não PSE)."},{"index":"3","when":"2026-07-23T07:49:00Z","kind":"prompt","author":"Marco Mendão","summary":"Criar bug crítico no Taskmark com o diagnóstico da investigação."},{"index":"4","when":"2026-07-23T08:03:26Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar ao B-005 as opções de fix de timestamps empatados (prioridade de evento, sort com reiceivedAt, sending anterior) para resolver spam + badge/timeline de uma vez; validar vs sugestões existentes."},{"index":"5","when":"2026-07-23T08:14:42Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-005 na worktree-1 (spam cron + ordenação/estado SMTP)."},{"index":"6","when":"2026-07-23T09:30:01Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work: sessão fechada; implementação B-005 na worktree-1 pronta (ainda sem commit)."}],"commits":[{"sha":"bf3e30f","repo":"coachid_app_api","date":"2026-07-23T10:31:55+01:00","author":"Marco Mendão","message":"fix wellness email spam and smtp sending timestamps"},{"sha":"de8e84c","repo":"coachid_app_frontend","date":"2026-07-23T10:31:56+01:00","author":"Marco Mendão","message":"fix smtp event ordering and admin ticket stats resilience"},{"sha":"7ef95ce","repo":"coachid-taskmark","date":"2026-07-23T10:31:56+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"8f1f289","repo":"coachid-taskmark","date":"2026-07-23T10:32:15+01:00","author":"Marco Mendão","message":"log B-005 commits on board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T08:14:42Z","ended":"2026-07-23T09:30:01Z","summary":"Implemented B-005 in worktree-1: onlyUnnotified+notified gate, companion notify-field merge, TZ day + per-day cron dedupe, events array + unique index, SMTP sort/priority + sending timestamp (Wellness+RPE), unit tests. Uncommitted in api/frontend worktree-1."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md":{"id":"B-010","title":"Wellness manual no planeamento exige treino/jogo","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":56000,"tags":["wellness","planeamento","i18n","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-003","epic":"E-003","created":"2026-07-28","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T08:51:19Z","completedAt":"2026-07-28T09:00:21Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md","description":"","acceptanceCriteria":[{"checked":true,"text":"Formulário de Wellness no planeamento não exige treino/jogo"},{"checked":true,"text":"Payload de criação omite `sourceAppointmentId` (fluxo day-based)"},{"checked":true,"text":"Copy do sheet descreve dia, não sessão"},{"checked":true,"text":"`navigation.training` presente em EN e PT"},{"checked":true,"text":"Nome auto-sugerido a partir do dia (`Wellness reminder (yyyy/MM/dd)`), editável"}],"acceptanceCriteriaRaw":"- [x] Formulário de Wellness no planeamento não exige treino/jogo\n- [x] Payload de criação omite `sourceAppointmentId` (fluxo day-based)\n- [x] Copy do sheet descreve dia, não sessão\n- [x] `navigation.training` presente em EN e PT\n- [x] Nome auto-sugerido a partir do dia (`Wellness reminder (yyyy/MM/dd)`), editável","reproSteps":"","fixCriteria":"- [x] Formulário de Wellness no planeamento não exige treino/jogo\n- [x] Payload de criação omite `sourceAppointmentId` (fluxo day-based)\n- [x] Copy do sheet descreve dia, não sessão\n- [x] `navigation.training` presente em EN e PT\n- [x] Nome auto-sugerido a partir do dia (`Wellness reminder (yyyy/MM/dd)`), editável","notes":"API já suporta `createOrUpdateManualDayReminder`. Regressão vs formulário day-based na develop; worktree-1 voltou a exigir sessão (T-007).","promptFeedback":[{"index":"1","when":"2026-07-28T08:51:19Z","kind":"prompt","author":"Marco Mendão","summary":"Wellness manual no planeamento exige treino/jogo; basta escolher o dia. Fix também navigation.training em falta nas traduções."},{"index":"2","when":"2026-07-28T08:51:59Z","kind":"feedback","author":"Marco Mendão","summary":"Formulário wellness só com dia; chave navigation.training adicionada."},{"index":"3","when":"2026-07-28T09:00:05Z","kind":"prompt","author":"Marco Mendão","summary":"Continuar a sugerir o nome do wellness baseado no dia escolhido (como no auto do treino)."},{"index":"4","when":"2026-07-28T09:00:21Z","kind":"feedback","author":"Marco Mendão","summary":"Nome sugerido pelo dia, alinhado à API; campo editável."}],"commits":[{"sha":"a82acdd","repo":"coachid_app_frontend","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"fix wellness day reminder without session"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T08:51:19Z","ended":"2026-07-28T08:51:59Z","summary":"Wellness day-based no planeamento; navigation.training EN/PT"},{"session":"2","actor":"Marco Mendão","started":"2026-07-28T09:00:05Z","ended":"2026-07-28T09:00:21Z","summary":"Auto-nome Wellness reminder (yyyy/MM/dd) ao mudar o dia"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md":{"id":"T-007","title":"Auto-gerar nome ao criar Wellness no planeamento (treino/jogo)","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":120,"actualMinutes":1,"actualMs":117000,"tags":["wellness","planeamento","naming","auto-generate"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-003","epic":"E-003","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T16:27:00Z","completedAt":"2026-07-23T16:32:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md","description":"Quando o utilizador cria um Wellness **directamente no planeamento** ao seleccionar um **treino** ou um **jogo**, o nome deve ser **auto-gerado**. O campo continua **editável**. O naming deve seguir a mesma abordagem do PSE (T-006): alinhado aos nomes gerados automaticamente quando o Wellness/PSE é criado via fluxo automático de criação de treino (reutilizar a mesma convenção do produto para o módulo wellness).","acceptanceCriteria":[{"checked":true,"text":"Ao criar Wellness no planeamento ligado a um treino, o nome é preenchido automaticamente"},{"checked":true,"text":"Ao criar Wellness no planeamento ligado a um jogo, o nome é preenchido automaticamente"},{"checked":true,"text":"O nome gerado segue a convenção automática já usada no produto para Wellness (espelho do comportamento PSE / criação automática de treino)"},{"checked":true,"text":"O utilizador pode editar o nome após a geração automática"},{"checked":true,"text":"Comportamento coerente com T-006 (PSE) na experiência de criação no planeamento"}],"acceptanceCriteriaRaw":"- [x] Ao criar Wellness no planeamento ligado a um treino, o nome é preenchido automaticamente\n- [x] Ao criar Wellness no planeamento ligado a um jogo, o nome é preenchido automaticamente\n- [x] O nome gerado segue a convenção automática já usada no produto para Wellness (espelho do comportamento PSE / criação automática de treino)\n- [x] O utilizador pode editar o nome após a geração automática\n- [x] Comportamento coerente com T-006 (PSE) na experiência de criação no planeamento","reproSteps":"","fixCriteria":"","notes":"General task no epic E-003. Espelho PSE: T-006.\n\nFormulário alinhado ao PSE: selector de treino/jogo + `sourceAppointmentId` no endpoint wellness-reminder.","promptFeedback":[{"index":"1","when":"2026-07-23T05:55:36Z","kind":"prompt","author":"Marco Mendão","summary":"Mesma tarefa que PSE: auto-gerar nome ao criar Wellness no planeamento (treino/jogo), editável."},{"index":"2","when":"2026-07-23T16:27:00Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-003, T-006, T-007."},{"index":"3","when":"2026-07-23T16:32:53Z","kind":"feedback","author":"Marco Mendão","summary":"Wellness form com sessão + auto-nome; API aceita sourceAppointmentId."}],"commits":[{"sha":"7af9580","repo":"coachid_app_frontend","date":"2026-07-23T16:33:23Z","author":"Marco Mendão","message":"default pse session today and auto-name planning reminders"},{"sha":"9997ba5","repo":"coachid_app_api","date":"2026-07-23T16:33:24Z","author":"Marco Mendão","message":"accept source session on wellness planning reminder"},{"sha":"1616a03","repo":"coachid-taskmark","date":"2026-07-23T17:33:39Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T16:27:00Z","ended":"2026-07-23T16:28:57Z","summary":"shared-batch: 117737 of 353213ms by points — auto-nome Wellness + session link"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md":{"id":"S-004","title":"Timeline de eventos no estado de envio de emails de notificação","type":"story","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":484,"actualMs":29051000,"tags":["wellness","ui","email","notifications"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-003","epic":"E-003","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T10:12:41Z","completedAt":"2026-07-23T10:15:03Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md","userStory":"Como treinador, quero ver uma timeline dos eventos de envio de email ao passar o rato sobre o estado do envio das notificações Wellness, para perceber com detalhe o que aconteceu no envio para o utilizador.","acceptanceCriteria":[{"checked":true,"text":"Ao fazer hover sobre o estado de envio de uma notificação por email, aparece uma timeline com os eventos colectados desse envio"},{"checked":true,"text":"Por defeito a timeline mostra apenas os 4 eventos mais recentes"},{"checked":true,"text":"Se existirem mais de 4 eventos, mostra apenas os 4 mais recentes e um botão ver mais por baixo (sem 5.o desfocado)"},{"checked":true,"text":"Ao clicar no botão “ver mais”, abre-se uma vista (tabela) com todos os eventos registados"},{"checked":true,"text":"A tabela / timeline usa o util partilhado de ordenação ([T-011](../../../E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md) / `sortEmailEventsDescending`): `timestamp` → prioridade lifecycle → `reiceivedAt`; mais recente primeiro"},{"checked":true,"text":"Com 4 ou menos eventos, não se mostra o botão ver mais"}],"acceptanceCriteriaRaw":"- [x] Ao fazer hover sobre o estado de envio de uma notificação por email, aparece uma timeline com os eventos colectados desse envio\n- [x] Por defeito a timeline mostra apenas os 4 eventos mais recentes\n- [x] Se existirem mais de 4 eventos, mostra apenas os 4 mais recentes e um botão ver mais por baixo (sem 5.o desfocado)\n- [x] Ao clicar no botão “ver mais”, abre-se uma vista (tabela) com todos os eventos registados\n- [x] A tabela / timeline usa o util partilhado de ordenação ([T-011](../../../E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md) / `sortEmailEventsDescending`): `timestamp` → prioridade lifecycle → `reiceivedAt`; mais recente primeiro\n- [x] Com 4 ou menos eventos, não se mostra o botão ver mais","tasksMarkdown":"Implementado via `EmailEventsTimelineHover` partilhado + `WellnessTableSendButton` (worktree-1).","children":[],"promptFeedback":[{"index":"1","when":"2026-07-23T05:03:07Z","kind":"prompt","author":"Marco Mendão","summary":"Story PSE+Wellness: hover no estado de envio de emails → timeline dos eventos; 4 visíveis + 5.º desfocado com “ver mais”; clique abre tabela completa ordenada por data (recente primeiro)."},{"index":"2","when":"2026-07-23T08:03:26Z","kind":"prompt","author":"Marco Mendão","summary":"Alinhar ordenação da timeline com o fix de timestamps empatados no B-005 (reiceivedAt + prioridade de evento)."},{"index":"3","when":"2026-07-23T10:12:41Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-003 e S-004."},{"index":"4","when":"2026-07-23T10:15:03Z","kind":"feedback","author":"Marco Mendão","summary":"Timeline partilhada + wiring Wellness; ordenação T-011."},{"index":"5","when":"2026-07-23T10:42:48Z","kind":"feedback","author":"Marco Mendão","summary":"Fix flicker hover timeline: sem onFocus/onBlur, modal=false, onCloseAutoFocus preventDefault."},{"index":"6","when":"2026-07-23T17:27:25Z","kind":"prompt","author":"Marco Mendão","summary":"Sem 5.o desfocado: so 4 eventos + botao ver mais por baixo."},{"index":"7","when":"2026-07-23T17:27:25Z","kind":"feedback","author":"Marco Mendão","summary":"Preview: 4 linhas nitidas; overflow -> ver mais abaixo."}],"commits":[{"sha":"049c8e7","repo":"coachid_app_frontend","date":"2026-07-23T18:27:13Z","author":"Marco Mendão","message":"show four timeline events without blurred fifth"},{"sha":"c08094f","repo":"coachid_app_frontend","date":"2026-07-23T11:42:58+01:00","author":"Marco Mendão","message":"fix email timeline hover flicker on mouse leave"},{"sha":"cb54d5e","repo":"coachid_app_frontend","date":"2026-07-23T11:28:11+01:00","author":"Marco Mendão","message":"add email events timeline on pse and wellness send status"},{"sha":"6d6aba6","repo":"coachid-taskmark","date":"2026-07-23T11:28:11+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"f4907eb","repo":"coachid-taskmark","date":"2026-07-23T18:27:14Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T10:12:41Z","ended":"2026-07-23T10:13:52Z","summary":"shared-batch: 71 of 142s by points — EmailEventsTimelineHover + WellnessTableSendButton"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T10:12:41Z","ended":"2026-07-23T18:27:13Z","summary":"auto-recovered: commit span"},{"session":"3","actor":"Marco Mendão","started":"2026-07-23T17:24:25Z","ended":"2026-07-23T17:27:25Z","summary":"shared-batch: 90000 of 180000ms by points — preview 4 + ver mais, sem blur"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/epic.md":{"id":"E-004","title":"Planeamento","type":"epic","status":"in_progress","priority":"medium","size":"—","points":29,"estimateMinutes":360,"actualMinutes":430,"actualMs":25820000,"tags":["module","planeamento"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T07:52:10Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/epic.md","goal":"Entregar e evoluir o módulo Planeamento — calendário, sessões, periodização e planeamento de treinos no CoachID.","scope":"- Modelos, APIs e UI de planeamento\n- Integração com Motor de exercícios e outros módulos quando necessário","outOfScope":"- Módulos Motor de exercícios, PSE, Wellness e Lineup (epics próprios)","successMetrics":"- Fluxos principais de planeamento utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"S-007","title":"Exportar calendário do planeamento em PDF (mensal e semana)","type":"story","status":"in_progress","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md"},{"id":"S-011","title":"Mostrar meso e micro ciclos no calendário de planeamento","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md"},{"id":"B-002","title":"Sheet criar jogo no planeamento mostra i18n em inglês","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md"},{"id":"B-009","title":"Export PDF semana omite jogos no domingo (filtro to date-only)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md"},{"id":"B-013","title":"Campo livre aparece em branco no relatório de unidade de treino","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md"},{"id":"B-023","title":"Planeamento — tipo de jogo amigável não é gravado","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md"},{"id":"B-024","title":"Planeamento — MD-x em falta quando jogos estão a 7 dias","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md"},{"id":"T-004","title":"Reporte treino — text-gray-400 para text-gray-600","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md"},{"id":"T-005","title":"Tab exercícios planeamento — ícone clipboard typography","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md"},{"id":"T-020","title":"Expanded layout — botão Voltar com hit target decente","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md"},{"id":"T-050","title":"Código sequencial UT/TS nos treinos da época/equipa","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md"},{"id":"T-053","title":"Intensidade do treino — níveis 1–10 e slider no formulário","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md"}],"commits":[{"sha":"2a43f76","repo":"coachid_app_frontend","date":"2026-07-29T14:47:29Z","author":"Marco Mendão","message":"show planning cycles on training report and summary"},{"sha":"0e00198","repo":"coachid_app_frontend","date":"2026-07-29T14:03:38Z","author":"Marco Mendão","message":"refine planning cycle labels and colours"},{"sha":"4922211","repo":"coachid_app_frontend","date":"2026-07-29T12:38:34Z","author":"Marco Mendão","message":"show planning cycles on pdf export"},{"sha":"dfbf0b8","repo":"coachid_app_frontend","date":"2026-07-29T12:28:20Z","author":"Marco Mendão","message":"edit planning cycles with date pickers"},{"sha":"0891c49","repo":"coachid_app_api","date":"2026-07-29T12:28:20Z","author":"Marco Mendão","message":"add variable planning cycle date ranges"},{"sha":"3871d02","repo":"coachid_app_frontend","date":"2026-07-29T12:14:28Z","author":"Marco Mendão","message":"add meso and micro cycle chip tooltips"},{"sha":"3649cf7","repo":"coachid_app_api","date":"2026-07-29T12:11:58Z","author":"Marco Mendão","message":"add planning meso and micro cycle API"},{"sha":"6c0ed61","repo":"coachid_app_frontend","date":"2026-07-29T12:11:58Z","author":"Marco Mendão","message":"show meso and micro cycles on planning calendar"},{"sha":"1397500","repo":"coachid_app_frontend","date":"2026-07-28T07:09:36Z","author":"Marco Mendão","message":"use outline button for expanded layout back"},{"sha":"bfa5e72","repo":"coachid_app_frontend","date":"2026-07-28T07:04:44Z","author":"Marco Mendão","message":"stack opponent cards one per row in overview sheet"},{"sha":"f1624c7","repo":"coachid_app_frontend","date":"2026-07-28T07:04:14Z","author":"Marco Mendão","message":"reuse opponent game cards in period overview sheet"},{"sha":"c7a1e5e","repo":"coachid_app_frontend","date":"2026-07-28T07:00:22Z","author":"Marco Mendão","message":"rename planning export button to Export"},{"sha":"fa92464","repo":"coachid_app_frontend","date":"2026-07-28T06:52:10Z","author":"Marco Mendão","message":"add margins around overview and opponents labels"},{"sha":"46efc55","repo":"coachid_app_frontend","date":"2026-07-28T06:49:52Z","author":"Marco Mendão","message":"fix opponent card meta label rendering"},{"sha":"62401ab","repo":"coachid_app_frontend","date":"2026-07-28T06:46:33Z","author":"Marco Mendão","message":"show opponent games as cards with match meta"},{"sha":"07aa3f3","repo":"coachid_app_frontend","date":"2026-07-28T06:43:09Z","author":"Marco Mendão","message":"add side padding to period overview"},{"sha":"2037f3c","repo":"coachid_app_frontend","date":"2026-07-28T06:41:44Z","author":"Marco Mendão","message":"remove overview top border line"},{"sha":"edb4010","repo":"coachid_app_frontend","date":"2026-07-28T06:38:50Z","author":"Marco Mendão","message":"add calendar top gap and tighten side padding"},{"sha":"77c635a","repo":"coachid_app_frontend","date":"2026-07-28T06:35:45Z","author":"Marco Mendão","message":"flush export header rule to frame edges"},{"sha":"8ebe978","repo":"coachid_app_frontend","date":"2026-07-28T06:29:26Z","author":"Marco Mendão","message":"shrink export team logo with object-cover"},{"sha":"fe14a3d","repo":"coachid_app_frontend","date":"2026-07-28T06:27:48Z","author":"Marco Mendão","message":"enlarge export donuts and appointment spacing"},{"sha":"16464ea","repo":"coachid_app_frontend","date":"2026-07-28T06:21:37Z","author":"Marco Mendão","message":"fix clipped export charts and add preview frame"},{"sha":"e469988","repo":"coachid_app_frontend","date":"2026-07-27T09:13:23Z","author":"Marco Mendão","message":"match planning export screen preview to print"},{"sha":"a14313f","repo":"coachid_app_frontend","date":"2026-07-27T09:03:43Z","author":"Marco Mendão","message":"middle-align page number with coachid mark"},{"sha":"f3ad2f7","repo":"coachid_app_frontend","date":"2026-07-27T08:56:36Z","author":"Marco Mendão","message":"grow week export calendar into leftover page space"},{"sha":"76a3d87","repo":"coachid_app_frontend","date":"2026-07-27T08:55:17Z","author":"Marco Mendão","message":"fit week export on one page without clipping opponents"},{"sha":"f8ca2c2","repo":"coachid_app_frontend","date":"2026-07-27T08:48:19Z","author":"Marco Mendão","message":"replace export footer with page mark icon"},{"sha":"7b6efb8","repo":"coachid_app_frontend","date":"2026-07-27T08:45:37Z","author":"Marco Mendão","message":"pin coachid footer to bottom of week export page"},{"sha":"e8eab06","repo":"coachid_app_frontend","date":"2026-07-27T08:42:02Z","author":"Marco Mendão","message":"expand week export calendar to fill page"},{"sha":"985b131","repo":"coachid_app_frontend","date":"2026-07-27T08:39:52Z","author":"Marco Mendão","message":"add match day labels to planning export"},{"sha":"5685506","repo":"coachid_app_frontend","date":"2026-07-27T08:38:08Z","author":"Marco Mendão","message":"add spacing between export chart and legend"},{"sha":"e55fb59","repo":"coachid_app_frontend","date":"2026-07-27T08:37:23Z","author":"Marco Mendão","message":"add week export margins above calendar and after opponents"},{"sha":"592fbc8","repo":"coachid_app_frontend","date":"2026-07-27T08:34:20Z","author":"Marco Mendão","message":"fix week export empty day vertical borders"},{"sha":"f6835dc","repo":"coachid_app_frontend","date":"2026-07-27T08:32:23Z","author":"Marco Mendão","message":"fit week export on one page and restore grid lines"},{"sha":"3515138","repo":"coachid_app_frontend","date":"2026-07-27T08:29:43Z","author":"Marco Mendão","message":"show two chart legend items per row"},{"sha":"9b56f22","repo":"coachid_app_api","date":"2026-07-27T08:28:54Z","author":"Marco Mendão","message":"fix dateTime range to include end day"},{"sha":"5e8afab","repo":"coachid_app_frontend","date":"2026-07-27T08:25:55Z","author":"Marco Mendão","message":"left-align week export overview summary headings"},{"sha":"f7dc48d","repo":"coachid_app_frontend","date":"2026-07-27T08:24:30Z","author":"Marco Mendão","message":"tighten week export spacing and center overview titles"},{"sha":"009cd06","repo":"coachid_app_frontend","date":"2026-07-27T08:19:06Z","author":"Marco Mendão","message":"hide assistant on planning export preview"},{"sha":"b4b6274","repo":"coachid_app_frontend","date":"2026-07-27T08:18:21Z","author":"Marco Mendão","message":"inline week export overview charts"},{"sha":"ce1993d","repo":"coachid-taskmark","date":"2026-07-27T08:08:45Z","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"d8566bf","repo":"coachid_app_frontend","date":"2026-07-27T08:08:01Z","author":"Marco Mendão","message":"add planning calendar PDF export for month and week"},{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"70125cc","repo":"coachid_app_frontend","date":"2026-07-27T08:57:39+01:00","author":"Marco Mendão","message":"fix planning game sheet i18n and training report gray"},{"sha":"ba76147","repo":"coachid-taskmark","date":"2026-07-23T07:25:56+01:00","author":"Marco Mendão","message":"update taskmark board"},{"sha":"bc6c50c","repo":"coachid-taskmark","date":"2026-07-23T06:41:56+01:00","author":"Marco Mendão","message":"update taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T05:41:56Z","ended":"2026-07-23T06:25:56Z","summary":"auto-recovered: commit span"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md":{"id":"B-002","title":"Sheet criar jogo no planeamento mostra i18n em inglês","type":"bug","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":10,"actualMinutes":1,"actualMs":60000,"tags":["planeamento","i18n","bug","sheet","jogo"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T07:52:10Z","completedAt":"2026-07-27T07:53:18Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md","description":"Na sheet de criar jogo do módulo de planeamento, o topo mostra textos em inglês (`Add game`, `Add a game to the calendar.`) mesmo com a aplicação em português.","acceptanceCriteria":[{"checked":true,"text":"Com locale português, o topo da sheet mostra strings traduzidas (não `Add game` / `Add a game to the calendar.`)"},{"checked":true,"text":"As chaves i18n correctas estão ligadas ao título e descrição da sheet"},{"checked":true,"text":"Comportamento verificado também noutros locales suportados (pelo menos EN e PT)"}],"acceptanceCriteriaRaw":"- [x] Com locale português, o topo da sheet mostra strings traduzidas (não `Add game` / `Add a game to the calendar.`)\n- [x] As chaves i18n correctas estão ligadas ao título e descrição da sheet\n- [x] Comportamento verificado também noutros locales suportados (pelo menos EN e PT)","reproSteps":"1. Definir a aplicação em português\n2. Abrir o módulo de planeamento\n3. Abrir a sheet de criar jogo\n4. Observar o título e subtítulo no topo da sheet","fixCriteria":"- [x] Com locale português, o topo da sheet mostra strings traduzidas (não `Add game` / `Add a game to the calendar.`)\n- [x] As chaves i18n correctas estão ligadas ao título e descrição da sheet\n- [x] Comportamento verificado também noutros locales suportados (pelo menos EN e PT)","notes":"General task no epic E-004 (sem user story).","promptFeedback":[{"index":"2","when":"2026-07-27T07:52:10Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-002 e T-004."},{"index":"1","when":"2026-07-23T05:33:47Z","kind":"prompt","author":"Marco Mendão","summary":"Bug i18n: sheet criar jogo no planeamento mostra \"Add game\" / \"Add a game to the calendar.\" com app em PT."}],"commits":[{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"70125cc","repo":"coachid_app_frontend","date":"2026-07-27T08:57:39+01:00","author":"Marco Mendão","message":"fix planning game sheet i18n and training report gray"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T07:52:10Z","ended":"2026-07-27T07:53:10Z","summary":"Fixed planning game sheet i18n. shared-batch: 1 of 3min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md":{"id":"B-009","title":"Export PDF semana omite jogos no domingo (filtro to date-only)","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":70000,"tags":["planeamento","pdf","export","games","api"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T08:27:44Z","completedAt":"2026-07-27T08:28:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md","description":"","acceptanceCriteria":[{"checked":true,"text":"Com `to` date-only (`YYYY-MM-DD`), listagens de `game`/`other` por `data.dateTime` incluem o dia final completo"},{"checked":true,"text":"Export semana mostra jogos no domingo"}],"acceptanceCriteriaRaw":"- [x] Com `to` date-only (`YYYY-MM-DD`), listagens de `game`/`other` por `data.dateTime` incluem o dia final completo\n- [x] Export semana mostra jogos no domingo","reproSteps":"","fixCriteria":"- [x] Com `to` date-only (`YYYY-MM-DD`), listagens de `game`/`other` por `data.dateTime` incluem o dia final completo\n- [x] Export semana mostra jogos no domingo","notes":"","promptFeedback":[{"index":"2","when":"2026-07-27T08:28:54Z","kind":"feedback","author":"Marco Mendão","summary":"API: to date-only usa $lt dia seguinte para dateTime."},{"index":"1","when":"2026-07-27T08:27:44Z","kind":"prompt","author":"Marco Mendão","summary":"Jogo no domingo aparece na UI mas não na exportação/preview PDF."}],"commits":[{"sha":"9b56f22","repo":"coachid_app_api","date":"2026-07-27T08:28:54Z","author":"Marco Mendão","message":"fix dateTime range to include end day"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T08:27:44Z","ended":"2026-07-27T08:28:54Z","summary":"API dateTime to-bound: exclusive next day so Sunday games appear in week export."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md":{"id":"B-013","title":"Campo livre aparece em branco no relatório de unidade de treino","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":206000,"tags":["planeamento","training-report","exercises","field-preset","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T15:57:58Z","completedAt":"2026-07-29T16:05:20Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md","description":"As imagens de campo geradas (S3/PNG) usadas no relatório de unidade de treino devem ser visualmente iguais às do editor de exercícios. Com **Configuração = Livre**, o campo no relatório aparece em branco (só o fundo branco), enquanto no editor o campo livre tem área de jogo preenchida e borda.","acceptanceCriteria":[{"checked":true,"text":"O render de export (`FieldPresetSvg` / media render) do preset `free` inclui a mesma área de jogo + borda que o editor"},{"checked":true,"text":"Imagens geradas a partir desse SVG deixam de parecer um campo em branco no relatório (modo white e green)"},{"checked":true,"text":"Comportamento alinhado entre editor e preview/impressão da unidade de treino para o preset Livre"},{"checked":true,"text":"Ao guardar um exercício, o export PNG re-renderiza o SVG para **green** e **white** (não só o plate) e faz upload das duas variantes para impressão do relatório"}],"acceptanceCriteriaRaw":"- [x] O render de export (`FieldPresetSvg` / media render) do preset `free` inclui a mesma área de jogo + borda que o editor\n- [x] Imagens geradas a partir desse SVG deixam de parecer um campo em branco no relatório (modo white e green)\n- [x] Comportamento alinhado entre editor e preview/impressão da unidade de treino para o preset Livre\n- [x] Ao guardar um exercício, o export PNG re-renderiza o SVG para **green** e **white** (não só o plate) e faz upload das duas variantes para impressão do relatório","reproSteps":"1. Abrir um exercício com preset **Livre** (e superfície sem cores / white).\n2. Confirmar no editor que o campo tem área cinza-clara e contorno.\n3. Abrir o relatório de unidade de treino que inclui esse exercício (modo campo sem cores).\n4. Observar o cartão: o fundo do campo fica branco/vazio face ao editor.","fixCriteria":"- [x] O render de export (`FieldPresetSvg` / media render) do preset `free` inclui a mesma área de jogo + borda que o editor\n- [x] Imagens geradas a partir desse SVG deixam de parecer um campo em branco no relatório (modo white e green)\n- [x] Comportamento alinhado entre editor e preview/impressão da unidade de treino para o preset Livre\n- [x] Ao guardar um exercício, o export PNG re-renderiza o SVG para **green** e **white** (não só o plate) e faz upload das duas variantes para impressão do relatório","notes":"Causa 1: `FieldPresetSvg` (media render) para `free` só desenhava o plate; o editor desenha plate + rect do playing area.\nCausa 2: no save do editor, o loop green/white chamava `exportExerciseSvgToPng` sem `setFieldSurface` — o SVG clonado ficava na superfície actual do editor; só o plate de fundo mudava.\nExercícios já exportados precisam de re-guardar para regenerar ambas as imagens no S3.","promptFeedback":[{"index":"1","when":"2026-07-29T15:57:34Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — garantir imagens de campo no relatório iguais ao editor; campo livre em branco; criar tarefa e resolver de imediato."},{"index":"2","when":"2026-07-29T15:57:58Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — corrigir FieldPresetSvg preset free."},{"index":"3","when":"2026-07-29T16:04:26Z","kind":"prompt","author":"Marco Mendão","summary":"Sempre gerar versão a cores e sem cores para impressão do relatório."},{"index":"4","when":"2026-07-29T16:05:20Z","kind":"feedback","author":"Marco Mendão","summary":"Save passa a re-renderizar SVG green e white antes do upload."}],"commits":[{"sha":"3c3afd3","repo":"coachid_app_frontend","date":"2026-07-29T16:05:20Z","author":"Marco Mendão","message":"export green and white exercise images with full surface render"},{"sha":"e9a5d47","repo":"coachid_app_frontend","date":"2026-07-29T15:58:11Z","author":"Marco Mendão","message":"fix free field plate in exercise media export"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T15:57:58Z","ended":"2026-07-29T16:00:30Z","summary":"Fixed FieldPresetSvg free: plate + playing area + border like editor."},{"session":"2","actor":"Marco Mendão","started":"2026-07-29T16:04:26Z","ended":"2026-07-29T16:05:20Z","summary":"Export PNG green+white with full SVG re-render on save."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md":{"id":"B-023","title":"Planeamento — tipo de jogo amigável não é gravado","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"tags":["planeamento","jogo","match-type","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T12:23:09Z","completedAt":"2026-08-03T12:26:10Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md","description":"Ao criar um jogo no planeamento e escolher tipo **Amigável**, o valor não é persistido. Ao reabrir o jogo para edição, aparece sempre como **Oficial**. O tipo de jogo também não aparece no cartão da vista semanal.\n\nCausa: `matchType` existe só no formulário UI; não é enviado nas mutations, não existe no API `GameData`/DTOs, e o mapper de edição força `Official`.","acceptanceCriteria":[{"checked":true,"text":"Tipo de jogo (oficial / amigável / treino) é gravado no create e update"},{"checked":true,"text":"Ao editar o jogo, o formulário mostra o tipo gravado"},{"checked":true,"text":"O cartão da vista semanal mostra o tipo de jogo"},{"checked":false,"text":"Fix no main (`coachid_app_api` + `coachid_app_frontend`), não worktrees"}],"acceptanceCriteriaRaw":"- [x] Tipo de jogo (oficial / amigável / treino) é gravado no create e update\n- [x] Ao editar o jogo, o formulário mostra o tipo gravado\n- [x] O cartão da vista semanal mostra o tipo de jogo\n- [ ] Fix no main (`coachid_app_api` + `coachid_app_frontend`), não worktrees","reproSteps":"1. Ir ao planeamento\n2. Clicar em novo jogo\n3. Seleccionar adversário\n4. Modificar o tipo de jogo para amigável\n5. Gravar\n6. No planeamento editar o jogo","fixCriteria":"- [x] Tipo de jogo (oficial / amigável / treino) é gravado no create e update\n- [x] Ao editar o jogo, o formulário mostra o tipo gravado\n- [x] O cartão da vista semanal mostra o tipo de jogo\n- [ ] Fix no main (`coachid_app_api` + `coachid_app_frontend`), não worktrees","notes":"Persistir `matchType` lowercase (`official` | `friendly` | `training`) alinhado com `site`.","promptFeedback":[{"index":"1","when":"2026-08-03T12:23:09Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — bug: tipo amigável não grava; criar e resolver no main; mostrar tipo no cartão semanal."},{"index":"2","when":"2026-08-03T12:26:10Z","kind":"feedback","author":"Marco Mendão","summary":"Fixed on main: matchType persisted and shown on weekly card."}],"commits":[{"sha":"d9cb0e0","repo":"coachid_app_api","date":"2026-08-03T12:26:34Z","author":"Marco Mendão","message":"fix B-023 persist game match type"},{"sha":"c8ec2d7","repo":"coachid_app_frontend","date":"2026-08-03T12:26:34Z","author":"Marco Mendão","message":"fix B-023 persist and show match type"},{"sha":"ee3432e","repo":"coachid-taskmark","date":"2026-08-03T12:26:34Z","author":"Marco Mendão","message":"add and complete B-023 match type bug"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T12:23:09Z","ended":"2026-08-03T12:26:10Z","summary":"Persist matchType API+FE and show on week card"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md":{"id":"B-024","title":"Planeamento — MD-x em falta quando jogos estão a 7 dias","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":4,"actualMs":252000,"tags":["planeamento","match-day","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T12:41:00Z","completedAt":"2026-08-03T12:45:12Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md","description":"Quando dois jogos caem no mesmo dia da semana (intervalo exacto de 7 dias), os labels `MD-1`…`MD-6` entre o `MD+1` do primeiro e o `MD` do segundo não aparecem. O segundo jogo mostra `MD` / `MD+1`, mas os dias anteriores ficam sem countdown.\n\nCausa: `matchDayLabelForDay` suprime toda a runway pré-jogo se `next - 7 dias === prev` (coincidência do MD-7 com o jogo anterior).","acceptanceCriteria":[{"checked":true,"text":"Com jogos a exactamente 7 dias, os dias livres mostram MD-x (ex.: MD-3…MD-1)"},{"checked":true,"text":"Dia do jogo anterior continua MD; dia seguinte continua MD+1 (prioridade sobre MD-n)"},{"checked":true,"text":"Intervalos ≠ 7 dias continuam correctos"},{"checked":true,"text":"Testes unitários actualizados; fix no main `coachid_app_api`"}],"acceptanceCriteriaRaw":"- [x] Com jogos a exactamente 7 dias, os dias livres mostram MD-x (ex.: MD-3…MD-1)\n- [x] Dia do jogo anterior continua MD; dia seguinte continua MD+1 (prioridade sobre MD-n)\n- [x] Intervalos ≠ 7 dias continuam correctos\n- [x] Testes unitários actualizados; fix no main `coachid_app_api`","reproSteps":"1. No planeamento, ter dois jogos no mesmo weekday a 7 dias (ex.: 23 e 30 de julho).\n2. Abrir a vista mensal/semanal.\n3. Observar que os dias entre MD+1 do primeiro e MD do segundo não têm MD-x (excepto MD+1 do primeiro).","fixCriteria":"- [x] Com jogos a exactamente 7 dias, os dias livres mostram MD-x (ex.: MD-3…MD-1)\n- [x] Dia do jogo anterior continua MD; dia seguinte continua MD+1 (prioridade sobre MD-n)\n- [x] Intervalos ≠ 7 dias continuam correctos\n- [x] Testes unitários actualizados; fix no main `coachid_app_api`","notes":"Remover o guard `runwayStartYmd === prev`; o dia do jogo já é tratado por `gameSet.has → MD`.","promptFeedback":[{"index":"1","when":"2026-08-03T12:43:58Z","kind":"prompt","author":"Marco Mendão","summary":"Resolver MD-x em falta entre jogos semanais (7 dias); ecrã produção 23/30 jul."},{"index":"2","when":"2026-08-03T12:45:12Z","kind":"feedback","author":"Marco Mendão","summary":"Fixed on main API; weekly MD-x labels restored."}],"commits":[{"sha":"21e380f","repo":"coachid_app_api","date":"2026-08-03T12:45:12Z","author":"Marco Mendão","message":"fix B-024 weekly match day MD-x labels"},{"sha":"cdcc218","repo":"coachid-taskmark","date":"2026-08-03T12:45:13Z","author":"Marco Mendão","message":"add and complete B-024 weekly MD-x bug"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T12:41:00Z","ended":"2026-08-03T12:45:12Z","summary":"Removed 7-day runway suppress; show MD-x between weekly fixtures"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md":{"id":"T-004","title":"Reporte treino — text-gray-400 para text-gray-600","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":180000,"tags":["planeamento","ui","reporte-treino","typography"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T07:52:10Z","completedAt":"2026-07-27T07:53:18Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md","description":"No reporte de treino (**Unidade de treino**), todos os elementos que usam a classe `.text-gray-400` devem passar a usar `.text-gray-600`.","acceptanceCriteria":[{"checked":true,"text":"No reporte / Unidade de treino, nenhum texto relevante permanece com `.text-gray-400` onde deveria ser `.text-gray-600`"},{"checked":true,"text":"Todos os elementos anteriormente com `.text-gray-400` nesse contexto usam `.text-gray-600`"},{"checked":true,"text":"Alteração verificada visualmente no reporte de treino"}],"acceptanceCriteriaRaw":"- [x] No reporte / Unidade de treino, nenhum texto relevante permanece com `.text-gray-400` onde deveria ser `.text-gray-600`\n- [x] Todos os elementos anteriormente com `.text-gray-400` nesse contexto usam `.text-gray-600`\n- [x] Alteração verificada visualmente no reporte de treino","reproSteps":"","fixCriteria":"","notes":"General task no epic E-004.","promptFeedback":[{"index":"2","when":"2026-07-27T07:52:10Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-002 e T-004."},{"index":"1","when":"2026-07-23T05:52:44Z","kind":"prompt","author":"Marco Mendão","summary":"Reporte treino (Unidade de treino): text-gray-400 → text-gray-600."}],"commits":[{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"70125cc","repo":"coachid_app_frontend","date":"2026-07-27T08:57:39+01:00","author":"Marco Mendão","message":"fix planning game sheet i18n and training report gray"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T07:52:10Z","ended":"2026-07-27T07:55:10Z","summary":"text-gray-400 → text-gray-600 on training report. shared-batch: 2 of 3min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md":{"id":"T-005","title":"Tab exercícios planeamento — ícone clipboard typography","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":50,"actualMinutes":63,"actualMs":3788000,"tags":["planeamento","ui","icon","exercicios"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T17:03:00Z","completedAt":"2026-07-23T17:05:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md","description":"Na tab de exercícios do módulo de planeamento, o ícone (actualmente de utilizador) deve ser o mesmo ícone de exercícios da sidebar do sistema: **clipboard typography**.","acceptanceCriteria":[{"checked":true,"text":"O ícone da tab de exercícios no planeamento é o **clipboard typography**"},{"checked":true,"text":"O ícone coincide com o usado para exercícios na sidebar do sistema"},{"checked":true,"text":"O ícone anterior de utilizador deixa de ser usado nessa tab"}],"acceptanceCriteriaRaw":"- [x] O ícone da tab de exercícios no planeamento é o **clipboard typography**\n- [x] O ícone coincide com o usado para exercícios na sidebar do sistema\n- [x] O ícone anterior de utilizador deixa de ser usado nessa tab","reproSteps":"","fixCriteria":"","notes":"General task no epic E-004.","promptFeedback":[{"index":"1","when":"2026-07-23T05:52:44Z","kind":"prompt","author":"Marco Mendão","summary":"Tab exercícios no planeamento: ícone utilizador → clipboard typography (igual sidebar exercícios)."},{"index":"2","when":"2026-07-23T17:04:35Z","kind":"prompt","author":"Marco Mendão","summary":"Tabs PSE/Wellness = ícones sidebar; tab exercícios treino = clipboard typography (motor exercícios)."},{"index":"3","when":"2026-07-23T17:05:30Z","kind":"feedback","author":"Marco Mendão","summary":"Tab + painel treino: IconClipboardTypography."}],"commits":[{"sha":"bff0870","repo":"coachid_app_frontend","date":"2026-07-23T18:05:31Z","author":"Marco Mendão","message":"align health and exercise tab icons with sidebar"},{"sha":"d8bd4af","repo":"coachid-taskmark","date":"2026-07-23T18:05:31Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T17:03:00Z","ended":"2026-07-23T17:03:37Z","summary":"shared-batch: 37500 of 150000ms by points — tab exercícios clipboard typography"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T17:03:00Z","ended":"2026-07-23T18:05:31Z","summary":"auto-recovered: commit span"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md":{"id":"T-020","title":"Expanded layout — botão Voltar com hit target decente","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":66000,"tags":["ui","ux","expanded-layout","planeamento"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-28","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:08:30Z","completedAt":"2026-07-28T07:09:36Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md","description":"Na top bar do layout expandido, a ação “Voltar” parece um link de texto (área de clique pequena e affordance fraca). Deve usar o `Button` do design system, com hit target confortável e alinhamento visual com o resto da barra (marca, ações, Imprimir).","acceptanceCriteria":[{"checked":true,"text":"“Voltar” no `ExpandedTopBar` é um `Button` (não texto estilo link)"},{"checked":true,"text":"Hit target adequado (altura ~sm / padding) em desktop e mobile"},{"checked":true,"text":"Label acessível (`aria-label` quando o texto está oculto no mobile)"},{"checked":true,"text":"Encaixa no visual da top bar expandida (ghost/outline, sem competir com CTAs primários à direita)"},{"checked":true,"text":"Comportamento de navegação existente mantém-se (`back` / `replace` / navigation guard)"}],"acceptanceCriteriaRaw":"- [x] “Voltar” no `ExpandedTopBar` é um `Button` (não texto estilo link)\n- [x] Hit target adequado (altura ~sm / padding) em desktop e mobile\n- [x] Label acessível (`aria-label` quando o texto está oculto no mobile)\n- [x] Encaixa no visual da top bar expandida (ghost/outline, sem competir com CTAs primários à direita)\n- [x] Comportamento de navegação existente mantém-se (`back` / `replace` / navigation guard)","reproSteps":"","fixCriteria":"","notes":"Ficheiro: `src/components/layout/ExpandedLayout/ExpandedTopBar.tsx`.","promptFeedback":[{"index":"2","when":"2026-07-28T07:09:36Z","kind":"feedback","author":"Marco Mendão","summary":"Voltar como Button outline com hit target e aria-label."},{"index":"1","when":"2026-07-28T07:08:30Z","kind":"prompt","author":"Marco Mendão","summary":"Reformular back no layout expandido: botão em vez de link; criar tarefa e executar."}],"commits":[{"sha":"1397500","repo":"coachid_app_frontend","date":"2026-07-28T07:09:36Z","author":"Marco Mendão","message":"use outline button for expanded layout back"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:08:30Z","ended":"2026-07-28T07:09:36Z","summary":"ExpandedTopBar back → Button outline sm."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md":{"id":"T-050","title":"Código sequencial UT/TS nos treinos da época/equipa","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":9,"actualMs":542000,"tags":["planeamento","treino","codigo","i18n","reporte-treino"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:53:28Z","completedAt":"2026-08-12T00:01:25Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md","description":"Adicionar um **código de unidade de treino** a cada treino de uma época/equipa.\n\n- Prefixo localizado: **UT** (Unidade de Treino, PT) ou **TS** (Training Session, EN).\n- Número sequencial cronológico dentro da época/equipa: primeiro treino → `UT1` / `TS1`, segundo → `UT2` / `TS2`, etc.\n- Se for criado (ou reagendado) um treino **entre** treinos existentes (ex.: entre UT1 e UT2), o novo treino assume o número da posição cronológica e os posteriores são **renumerados** (ex.: o antigo UT2 passa a UT3, e assim por diante).\n- O código deve ser **visível** no cabeçalho do reporte de unidade de treino, nas views do planeamento, e no formulário de edição/adição de um treino.","acceptanceCriteria":[{"checked":true,"text":"Cada treino de uma época/equipa tem um código `UT{n}` (locale PT) ou `TS{n}` (locale EN)"},{"checked":true,"text":"`n` reflecte a ordem cronológica dos treinos nessa época/equipa (1 = mais antigo)"},{"checked":true,"text":"Ao inserir ou mover um treino entre datas existentes, os códigos são recalculados para manter a sequência cronológica"},{"checked":true,"text":"O código aparece no cabeçalho do reporte de unidade de treino"},{"checked":true,"text":"No reporte, o código aparece numa coluna própria ao lado do microciclo (não no título do banner)"},{"checked":true,"text":"O código aparece nas views do planeamento (calendário / listagens relevantes)"},{"checked":true,"text":"O código aparece no formulário de criação e edição de treino"}],"acceptanceCriteriaRaw":"- [x] Cada treino de uma época/equipa tem um código `UT{n}` (locale PT) ou `TS{n}` (locale EN)\n- [x] `n` reflecte a ordem cronológica dos treinos nessa época/equipa (1 = mais antigo)\n- [x] Ao inserir ou mover um treino entre datas existentes, os códigos são recalculados para manter a sequência cronológica\n- [x] O código aparece no cabeçalho do reporte de unidade de treino\n- [x] No reporte, o código aparece numa coluna própria ao lado do microciclo (não no título do banner)\n- [x] O código aparece nas views do planeamento (calendário / listagens relevantes)\n- [x] O código aparece no formulário de criação e edição de treino","reproSteps":"","fixCriteria":"","notes":"- Scope: treinos da mesma época/equipa (não jogos). Renumeração em create / update / delete **e ao listar** (`getTrainings`) para backfill.\n- Persistência: `data.sequenceNumber`; cartões: `UT3 · …` / `TS3 · …`.\n- Ordem: `date` → `hourStart` → `_id`.\n- Follow-up: DayView usava `event.title` — passou a `getEventCardTitle`.","promptFeedback":[{"index":"1","when":"2026-08-10T06:08:27Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa: código UT/TS sequencial cronológico nos treinos; visível no reporte, planeamento e formulário; renumerar ao inserir entre treinos."},{"index":"2","when":"2026-08-11T16:53:28Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa a tarefa T-050"},{"index":"3","when":"2026-08-11T18:21:59Z","kind":"prompt","author":"Marco Mendão","summary":"UTX deve aparecer nos cartões no nome do treino (semana, mês, etc.)"},{"index":"4","when":"2026-08-11T18:23:46Z","kind":"prompt","author":"Marco Mendão","summary":"Remover label Detalhes do treino; UTX no cabeçalho da unidade de treino"},{"index":"5","when":"2026-08-12T00:00:51Z","kind":"prompt","author":"Marco Mendão","summary":"Na unidade de treino o código deve aparecer ao lado do microciclo na sua própria coluna"}],"commits":[{"sha":"28ef182","repo":"coachid_app_api","date":"2026-08-11T23:58:47Z","author":"Marco Mendão","message":"add sequential training unit sequence numbers"},{"sha":"d0e3fe8","repo":"coachid_app_api (worktree-1)","date":"2026-08-11T23:58:47Z","author":"Marco Mendão","message":"add sequential training unit sequence numbers"},{"sha":"4c5cfdc","repo":"coachid_app_frontend","date":"2026-08-11T23:58:47Z","author":"Marco Mendão","message":"show UT/TS codes on planning cards and training report"},{"sha":"86a310d","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-11T23:58:48Z","author":"Marco Mendão","message":"show UT/TS codes on planning cards and training report"},{"sha":"44bc4e6","repo":"coachid_app_frontend","date":"2026-08-12T00:03:05Z","author":"Marco Mendão","message":"show training unit code beside microcycle column"},{"sha":"7285646","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-12T00:03:05Z","author":"Marco Mendão","message":"show training unit code beside microcycle column"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:53:28Z","ended":"2026-08-11T17:00:12Z","summary":"API sequenceNumber + renumber; UI UT/TS on report, calendar, training form"},{"session":"2","actor":"Marco Mendão","started":"2026-08-11T18:21:59Z","ended":"2026-08-11T18:22:55Z","summary":"Fix cards: renumber on list + DayView uses getEventCardTitle with UT code"},{"session":"3","actor":"Marco Mendão","started":"2026-08-11T18:23:46Z","ended":"2026-08-11T18:24:34Z","summary":"Report: drop sessionDetails heading; UT in banner; renumber on getById"},{"session":"4","actor":"Marco Mendão","started":"2026-08-12T00:00:51Z","ended":"2026-08-12T00:01:25Z","summary":"Report: UT/TS code in own meta column beside microcycle"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md":{"id":"T-053","title":"Intensidade do treino — níveis 1–10 e slider no formulário","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["planeamento","treino","intensidade","slider","ui"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T00:03:29Z","completedAt":"2026-08-12T00:06:29Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md","description":"Os treinos passam a usar níveis de intensidade **1–10**, agrupados em labels:\n\n| Valores | Label |\n|---------|--------|\n| 1, 2 | Muito Leve |\n| 3, 4 | Leve |\n| 5, 6 | Moderado |\n| 7, 8 | Alto |\n| 9, 10 | Muito Alto |\n\nNo formulário de **adição/edição** do treino, o utilizador escolhe a intensidade com um picker estilo **slider** (controlado), no padrão [shadcn/ui Slider — Controlled](https://ui.shadcn.com/docs/components/base/slider#controlled).","acceptanceCriteria":[{"checked":true,"text":"A intensidade do treino usa a escala **1–10** com os mapeamentos de label acima (i18n)"},{"checked":true,"text":"No formulário de adição do treino existe um **slider** para escolher a intensidade"},{"checked":true,"text":"No formulário de edição do treino o mesmo slider carrega e grava o valor actual"},{"checked":true,"text":"O slider mostra (ou acompanha) o valor numérico e/ou a label correspondente ao intervalo seleccionado"},{"checked":true,"text":"O valor escolhido é persistido e reflectido onde a intensidade do treino já é mostrada no produto"},{"checked":true,"text":"Implementação alinhada ao componente Slider do design system / shadcn (modo controlled)"}],"acceptanceCriteriaRaw":"- [x] A intensidade do treino usa a escala **1–10** com os mapeamentos de label acima (i18n)\n- [x] No formulário de adição do treino existe um **slider** para escolher a intensidade\n- [x] No formulário de edição do treino o mesmo slider carrega e grava o valor actual\n- [x] O slider mostra (ou acompanha) o valor numérico e/ou a label correspondente ao intervalo seleccionado\n- [x] O valor escolhido é persistido e reflectido onde a intensidade do treino já é mostrada no produto\n- [x] Implementação alinhada ao componente Slider do design system / shadcn (modo controlled)","reproSteps":"","fixCriteria":"","notes":"Referência UI: https://ui.shadcn.com/docs/components/base/slider#controlled \nConfirmar se o modelo/API já guarda intensidade numérica 1–10 ou se precisa de migração/adaptação de labels antigas.","promptFeedback":[{"index":"1","when":"2026-08-10T06:35:37Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — intensidade treino 1–10 (Muito Leve…Muito Alto); slider controlled no form add/edit (shadcn Slider)."},{"index":"2","when":"2026-08-12T00:03:29Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa as tarefas T-051, T-052, T-053, T-054"}],"commits":[{"sha":"f50bae5","repo":"coachid_app_frontend","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"},{"sha":"064e451","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T00:05:29Z","ended":"2026-08-12T00:06:29Z","summary":"Training intensity 1–10 slider + 5-band labels; shared-batch: 1 of 4min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md":{"id":"S-007","title":"Exportar calendário do planeamento em PDF (mensal e semana)","type":"story","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":22,"actualMs":1339000,"tags":["planeamento","pdf","export","calendar","preview"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T08:01:25Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md","userStory":"Como treinador, quero exportar o calendário de planeamento em PDF nas vistas **Mensal** e **Semana**, com preview antes de imprimir (como no reporte de treino), para partilhar ou imprimir o planeamento com cabeçalho, logo da equipa, eventos e métricas do overview.","acceptanceCriteria":[{"checked":true,"text":"É possível exportar o calendário do planeamento em PDF a partir das vistas **Mensal** e **Semana**"},{"checked":true,"text":"**Exportação mensal:** documento em formato **listagem**, mostrando apenas os dias com eventos (dias sem eventos omitidos)"},{"checked":true,"text":"Formato mensal do tipo:"},{"checked":true,"text":"**Exportação semana:** layout muito parecido à interface actual da vista semanal"},{"checked":true,"text":"Vista semana impressa em página **landscape**, para os elementos visuais caberem sem problema"},{"checked":true,"text":"Cada página tem um **cabeçalho** com informação geral (ex.: “Planeamento Janeiro 2026”), **logo da equipa** e restante branding/contexto esperado"},{"checked":true,"text":"Os **gráficos e métricas** da sheet de **overview** também aparecem nestes documentos"},{"checked":true,"text":"Existe um **preview** para visualizar o documento antes de imprimir/exportar, à semelhança do reporte de treino (unidade de treino)"},{"checked":true,"text":"Na **exportação semana**, os gráficos do “Resumo do período” ficam **inline** (na mesma linha)"},{"checked":true,"text":"O **assistente** não aparece no preview de export PDF"}],"acceptanceCriteriaRaw":"- [x] É possível exportar o calendário do planeamento em PDF a partir das vistas **Mensal** e **Semana**\n- [x] **Exportação mensal:** documento em formato **listagem**, mostrando apenas os dias com eventos (dias sem eventos omitidos)\n- [x] Formato mensal do tipo:\n ```\n Dia 12 de Março (Segunda-feira):\n - 09:00 - Treino\n - 11:00 - PSE\n ```\n- [x] **Exportação semana:** layout muito parecido à interface actual da vista semanal\n- [x] Vista semana impressa em página **landscape**, para os elementos visuais caberem sem problema\n- [x] Cada página tem um **cabeçalho** com informação geral (ex.: “Planeamento Janeiro 2026”), **logo da equipa** e restante branding/contexto esperado\n- [x] Os **gráficos e métricas** da sheet de **overview** também aparecem nestes documentos\n- [x] Existe um **preview** para visualizar o documento antes de imprimir/exportar, à semelhança do reporte de treino (unidade de treino)\n- [x] Na **exportação semana**, os gráficos do “Resumo do período” ficam **inline** (na mesma linha)\n- [x] O **assistente** não aparece no preview de export PDF","tasksMarkdown":"- [B-029](items/B-029-export-semana-cabecalhos-desformatados-md-x.md) — Export semana — cabeçalhos desformatados quando MD-X só até meio da semana","children":[{"id":"B-029","title":"Export semana — cabeçalhos desformatados quando MD-X só até meio da semana","type":"bug","status":"backlog","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/items/B-029-export-semana-cabecalhos-desformatados-md-x.md"}],"promptFeedback":[{"index":"57","when":"2026-07-28T07:04:44Z","kind":"feedback","author":"Marco Mendão","summary":"Sheet com adversários um por linha; export inalterado."},{"index":"56","when":"2026-07-28T07:04:44Z","kind":"prompt","author":"Marco Mendão","summary":"Sheet adversários: um cartão por linha; relatório mantém layout."},{"index":"55","when":"2026-07-28T07:04:14Z","kind":"feedback","author":"Marco Mendão","summary":"Cartões de adversário na sheet Resumo do planeamento."},{"index":"54","when":"2026-07-28T07:01:32Z","kind":"prompt","author":"Marco Mendão","summary":"Cartão de adversário do export também na sheet Resumo do planeamento."},{"index":"53","when":"2026-07-28T07:00:22Z","kind":"feedback","author":"Marco Mendão","summary":"Botão renomeado para Exportar."},{"index":"52","when":"2026-07-28T06:59:42Z","kind":"prompt","author":"Marco Mendão","summary":"Botão Exportar PDF → só Exportar."},{"index":"51","when":"2026-07-28T06:52:10Z","kind":"feedback","author":"Marco Mendão","summary":"Margens no Resumo do período e sob Adversários."},{"index":"50","when":"2026-07-28T06:51:22Z","kind":"prompt","author":"Marco Mendão","summary":"Margem acima de Resumo do período e abaixo de Adversários."},{"index":"49","when":"2026-07-28T06:49:52Z","kind":"feedback","author":"Marco Mendão","summary":"Meta do cartão de adversário já não mostra a chave i18n."},{"index":"48","when":"2026-07-28T06:49:04Z","kind":"prompt","author":"Marco Mendão","summary":"Label opponentCardMeta aparece como chave i18n."},{"index":"47","when":"2026-07-28T06:46:33Z","kind":"feedback","author":"Marco Mendão","summary":"Cartões de adversário com dia, duração e dia da semana."},{"index":"46","when":"2026-07-28T06:45:18Z","kind":"prompt","author":"Marco Mendão","summary":"Adversários em cartões com dia, duração e dia da semana."},{"index":"45","when":"2026-07-28T06:43:09Z","kind":"feedback","author":"Marco Mendão","summary":"Padding lateral no Resumo do período."},{"index":"44","when":"2026-07-28T06:42:51Z","kind":"prompt","author":"Marco Mendão","summary":"Padding lateral na secção Resumo do período."},{"index":"43","when":"2026-07-28T06:41:44Z","kind":"feedback","author":"Marco Mendão","summary":"Linha acima de Resumo do período removida."},{"index":"42","when":"2026-07-28T06:41:04Z","kind":"prompt","author":"Marco Mendão","summary":"Remover linha acima de Resumo do período."},{"index":"41","when":"2026-07-28T06:38:50Z","kind":"feedback","author":"Marco Mendão","summary":"Margem no topo do calendário; padding lateral do conteúdo reduzido."},{"index":"40","when":"2026-07-28T06:38:29Z","kind":"prompt","author":"Marco Mendão","summary":"Margem topo calendário vs cabeçalho; menos padding lateral do conteúdo."},{"index":"39","when":"2026-07-28T06:35:45Z","kind":"feedback","author":"Marco Mendão","summary":"Linha do cabeçalho colada à frame; topo mais alinhado."},{"index":"38","when":"2026-07-28T06:34:37Z","kind":"prompt","author":"Marco Mendão","summary":"Linha do cabeçalho colar à frame; menos padding/margin no topo."},{"index":"37","when":"2026-07-28T06:29:26Z","kind":"feedback","author":"Marco Mendão","summary":"Logo da equipa mais pequeno com object-cover."},{"index":"36","when":"2026-07-28T06:29:09Z","kind":"prompt","author":"Marco Mendão","summary":"Logo menor e object-cover para manter aspect ratio."},{"index":"35","when":"2026-07-28T06:27:48Z","kind":"feedback","author":"Marco Mendão","summary":"Donuts maiores; mais espaçamento entre appointments."},{"index":"34","when":"2026-07-28T06:27:14Z","kind":"prompt","author":"Marco Mendão","summary":"Bigger donut graphs; more spacing between calendar appointments."},{"index":"33","when":"2026-07-28T06:21:37Z","kind":"feedback","author":"Marco Mendão","summary":"Gráficos sem corte; frame com margem no preview."},{"index":"32","when":"2026-07-28T06:19:34Z","kind":"prompt","author":"Marco Mendão","summary":"Gráficos do overview cortados; frame + margem à volta do preview."},{"index":"31","when":"2026-07-27T09:13:23Z","kind":"feedback","author":"Marco Mendão","summary":"Preview no ecrã usa a mesma folha mm e estilos compactos que a impressão (sem 100vh)."},{"index":"30","when":"2026-07-27T09:10:19Z","kind":"prompt","author":"Marco Mendão","summary":"Certificar que a pré-visualização da impressão é igual à impressão em si."},{"index":"29","when":"2026-07-27T09:03:43Z","kind":"feedback","author":"Marco Mendão","summary":"Ícone como background do @bottom-right com `background-position: left center` + texto; alinhamento vertical ao meio com o número de página."},{"index":"28","when":"2026-07-27T09:03:08Z","kind":"prompt","author":"Marco Mendão","summary":"O número da página tem de estar alinhado ao meio (align-middle) com o ícone da CoachID."},{"index":"27","when":"2026-07-27T08:56:36Z","kind":"prompt","author":"Marco Mendão","summary":"Calendário no máximo espaço sem nova página."},{"index":"26","when":"2026-07-27T08:55:17Z","kind":"prompt","author":"Marco Mendão","summary":"Adversários cortados e 2 páginas — forçar 1 página."},{"index":"25","when":"2026-07-27T08:48:19Z","kind":"prompt","author":"Marco Mendão","summary":"Remover footer; só números de página com ícone CoachID."},{"index":"24","when":"2026-07-27T08:45:37Z","kind":"prompt","author":"Marco Mendão","summary":"Footer CoachID no final da página."},{"index":"23","when":"2026-07-27T08:42:02Z","kind":"prompt","author":"Marco Mendão","summary":"Calendário ocupar máximo espaço sem nova página."},{"index":"21","when":"2026-07-27T08:39:52Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar match days MD±X na exportação."},{"index":"22","when":"2026-07-27T08:39:52Z","kind":"feedback","author":"Marco Mendão","summary":"Labels MD na grelha semana e listagem mensal."},{"index":"20","when":"2026-07-27T08:38:08Z","kind":"prompt","author":"Marco Mendão","summary":"Margem entre gráfico e legenda."},{"index":"18","when":"2026-07-27T08:37:23Z","kind":"prompt","author":"Marco Mendão","summary":"Margem acima do calendário e após adversários."},{"index":"16","when":"2026-07-27T08:34:20Z","kind":"prompt","author":"Marco Mendão","summary":"Dias sem eventos perdem linhas verticais na export semana."},{"index":"17","when":"2026-07-27T08:34:20Z","kind":"feedback","author":"Marco Mendão","summary":"Grelha semana em table com border-collapse para células vazias."},{"index":"14","when":"2026-07-27T08:32:23Z","kind":"prompt","author":"Marco Mendão","summary":"Espaçamento legendas; 1 página; linhas horizontais do calendário."},{"index":"15","when":"2026-07-27T08:32:23Z","kind":"feedback","author":"Marco Mendão","summary":"Sem min-height 100vh na semana; grelha com borders; legendas com mais gap."},{"index":"12","when":"2026-07-27T08:29:43Z","kind":"prompt","author":"Marco Mendão","summary":"Legendas dos gráficos com 2 valores por linha."},{"index":"13","when":"2026-07-27T08:29:43Z","kind":"feedback","author":"Marco Mendão","summary":"Legend grid 2 colunas no overview do export."},{"index":"10","when":"2026-07-27T08:25:55Z","kind":"prompt","author":"Marco Mendão","summary":"Alinhar à esquerda Resumo do período / Jogos e treinos."},{"index":"11","when":"2026-07-27T08:25:55Z","kind":"feedback","author":"Marco Mendão","summary":"Resumo e contagens alinhados à esquerda; gráficos continuam centrados."},{"index":"9","when":"2026-07-27T08:24:30Z","kind":"feedback","author":"Marco Mendão","summary":"Espaçamentos compactados; títulos do resumo centrados."},{"index":"8","when":"2026-07-27T08:24:16Z","kind":"prompt","author":"Marco Mendão","summary":"Compactar espaçamentos e centrar títulos do resumo para caber numa página."},{"index":"7","when":"2026-07-27T08:19:06Z","kind":"feedback","author":"Marco Mendão","summary":"Assistente oculto no preview de export PDF (como no reporte de treino)."},{"index":"6","when":"2026-07-27T08:19:06Z","kind":"prompt","author":"Marco Mendão","summary":"Não deve existir o assistente na preview de imprimir do export PDF."},{"index":"5","when":"2026-07-27T08:17:58Z","kind":"feedback","author":"Marco Mendão","summary":"Gráficos do resumo na export semana em grelha 3 colunas (inline)."},{"index":"4","when":"2026-07-27T08:16:53Z","kind":"prompt","author":"Marco Mendão","summary":"Vista semanal: gráficos do Resumo do período inline (mesma linha)."},{"index":"3","when":"2026-07-27T08:08:01Z","kind":"feedback","author":"Marco Mendão","summary":"Entregue: preview export PDF mês/semana (print), listagem + grid landscape, overview, i18n, botão nas vistas."},{"index":"2","when":"2026-07-27T08:01:25Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-007 completa."},{"index":"1","when":"2026-07-23T06:03:42Z","kind":"prompt","author":"Marco Mendão","summary":"Export PDF planeamento: Mensal (listagem só dias com eventos) e Semana (UI-like, landscape); cabeçalho + logo; gráficos/métricas overview; preview como reporte treino."}],"commits":[{"sha":"bfa5e72","repo":"coachid_app_frontend","date":"2026-07-28T07:04:44Z","author":"Marco Mendão","message":"stack opponent cards one per row in overview sheet"},{"sha":"f1624c7","repo":"coachid_app_frontend","date":"2026-07-28T07:04:14Z","author":"Marco Mendão","message":"reuse opponent game cards in period overview sheet"},{"sha":"c7a1e5e","repo":"coachid_app_frontend","date":"2026-07-28T07:00:22Z","author":"Marco Mendão","message":"rename planning export button to Export"},{"sha":"fa92464","repo":"coachid_app_frontend","date":"2026-07-28T06:52:10Z","author":"Marco Mendão","message":"add margins around overview and opponents labels"},{"sha":"46efc55","repo":"coachid_app_frontend","date":"2026-07-28T06:49:52Z","author":"Marco Mendão","message":"fix opponent card meta label rendering"},{"sha":"62401ab","repo":"coachid_app_frontend","date":"2026-07-28T06:46:33Z","author":"Marco Mendão","message":"show opponent games as cards with match meta"},{"sha":"07aa3f3","repo":"coachid_app_frontend","date":"2026-07-28T06:43:09Z","author":"Marco Mendão","message":"add side padding to period overview"},{"sha":"2037f3c","repo":"coachid_app_frontend","date":"2026-07-28T06:41:44Z","author":"Marco Mendão","message":"remove overview top border line"},{"sha":"edb4010","repo":"coachid_app_frontend","date":"2026-07-28T06:38:50Z","author":"Marco Mendão","message":"add calendar top gap and tighten side padding"},{"sha":"77c635a","repo":"coachid_app_frontend","date":"2026-07-28T06:35:45Z","author":"Marco Mendão","message":"flush export header rule to frame edges"},{"sha":"8ebe978","repo":"coachid_app_frontend","date":"2026-07-28T06:29:26Z","author":"Marco Mendão","message":"shrink export team logo with object-cover"},{"sha":"fe14a3d","repo":"coachid_app_frontend","date":"2026-07-28T06:27:48Z","author":"Marco Mendão","message":"enlarge export donuts and appointment spacing"},{"sha":"16464ea","repo":"coachid_app_frontend","date":"2026-07-28T06:21:37Z","author":"Marco Mendão","message":"fix clipped export charts and add preview frame"},{"sha":"e469988","repo":"coachid_app_frontend","date":"2026-07-27T09:13:23Z","author":"Marco Mendão","message":"match planning export screen preview to print"},{"sha":"a14313f","repo":"coachid_app_frontend","date":"2026-07-27T09:03:43Z","author":"Marco Mendão","message":"middle-align page number with coachid mark"},{"sha":"f3ad2f7","repo":"coachid_app_frontend","date":"2026-07-27T08:56:36Z","author":"Marco Mendão","message":"grow week export calendar into leftover page space"},{"sha":"76a3d87","repo":"coachid_app_frontend","date":"2026-07-27T08:55:17Z","author":"Marco Mendão","message":"fit week export on one page without clipping opponents"},{"sha":"f8ca2c2","repo":"coachid_app_frontend","date":"2026-07-27T08:48:19Z","author":"Marco Mendão","message":"replace export footer with page mark icon"},{"sha":"7b6efb8","repo":"coachid_app_frontend","date":"2026-07-27T08:45:37Z","author":"Marco Mendão","message":"pin coachid footer to bottom of week export page"},{"sha":"e8eab06","repo":"coachid_app_frontend","date":"2026-07-27T08:42:02Z","author":"Marco Mendão","message":"expand week export calendar to fill page"},{"sha":"985b131","repo":"coachid_app_frontend","date":"2026-07-27T08:39:52Z","author":"Marco Mendão","message":"add match day labels to planning export"},{"sha":"5685506","repo":"coachid_app_frontend","date":"2026-07-27T08:38:08Z","author":"Marco Mendão","message":"add spacing between export chart and legend"},{"sha":"e55fb59","repo":"coachid_app_frontend","date":"2026-07-27T08:37:23Z","author":"Marco Mendão","message":"add week export margins above calendar and after opponents"},{"sha":"592fbc8","repo":"coachid_app_frontend","date":"2026-07-27T08:34:20Z","author":"Marco Mendão","message":"fix week export empty day vertical borders"},{"sha":"f6835dc","repo":"coachid_app_frontend","date":"2026-07-27T08:32:23Z","author":"Marco Mendão","message":"fit week export on one page and restore grid lines"},{"sha":"3515138","repo":"coachid_app_frontend","date":"2026-07-27T08:29:43Z","author":"Marco Mendão","message":"show two chart legend items per row"},{"sha":"5e8afab","repo":"coachid_app_frontend","date":"2026-07-27T08:25:55Z","author":"Marco Mendão","message":"left-align week export overview summary headings"},{"sha":"f7dc48d","repo":"coachid_app_frontend","date":"2026-07-27T08:24:30Z","author":"Marco Mendão","message":"tighten week export spacing and center overview titles"},{"sha":"009cd06","repo":"coachid_app_frontend","date":"2026-07-27T08:19:06Z","author":"Marco Mendão","message":"hide assistant on planning export preview"},{"sha":"b4b6274","repo":"coachid_app_frontend","date":"2026-07-27T08:18:21Z","author":"Marco Mendão","message":"inline week export overview charts"},{"sha":"ce1993d","repo":"coachid-taskmark","date":"2026-07-27T08:08:45Z","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"d8566bf","repo":"coachid_app_frontend","date":"2026-07-27T08:08:01Z","author":"Marco Mendão","message":"add planning calendar PDF export for month and week"}],"workLog":[{"session":"16","actor":"Marco Mendão","started":"2026-07-28T07:04:44Z","ended":"2026-07-28T07:04:44Z","summary":"Overview sheet: one opponent card per row."},{"session":"15","actor":"Marco Mendão","started":"2026-07-28T07:01:32Z","ended":"2026-07-28T07:04:14Z","summary":"Shared OpponentGameCard in period overview sheet + export."},{"session":"14","actor":"Marco Mendão","started":"2026-07-28T06:59:42Z","ended":"2026-07-28T07:00:22Z","summary":"Button label Exportar PDF → Exportar / Export."},{"session":"13","actor":"Marco Mendão","started":"2026-07-28T06:51:22Z","ended":"2026-07-28T06:52:10Z","summary":"Margin above Resumo do período; margin below Adversários."},{"session":"12","actor":"Marco Mendão","started":"2026-07-28T06:49:04Z","ended":"2026-07-28T06:49:52Z","summary":"Compose opponent card meta in code; drop broken i18n key."},{"session":"11","actor":"Marco Mendão","started":"2026-07-28T06:45:18Z","ended":"2026-07-28T06:46:33Z","summary":"Opponent games as cards with weekday, date, duration."},{"session":"10","actor":"Marco Mendão","started":"2026-07-28T06:42:51Z","ended":"2026-07-28T06:43:09Z","summary":"Side padding on Resumo do período section."},{"session":"9","actor":"Marco Mendão","started":"2026-07-28T06:41:04Z","ended":"2026-07-28T06:41:44Z","summary":"Removed border above Resumo do período."},{"session":"8","actor":"Marco Mendão","started":"2026-07-28T06:38:29Z","ended":"2026-07-28T06:38:50Z","summary":"Calendar top margin 4mm; body side padding 3.5mm (header unchanged)."},{"session":"7","actor":"Marco Mendão","started":"2026-07-28T06:34:37Z","ended":"2026-07-28T06:35:45Z","summary":"Header border flush to frame; less top padding."},{"session":"6","actor":"Marco Mendão","started":"2026-07-28T06:29:09Z","ended":"2026-07-28T06:29:26Z","summary":"Smaller team logo with object-cover."},{"session":"5","actor":"Marco Mendão","started":"2026-07-28T06:27:14Z","ended":"2026-07-28T06:27:48Z","summary":"Larger week export donuts (80px) and more gap between appointments."},{"session":"4","actor":"Marco Mendão","started":"2026-07-28T06:19:34Z","ended":"2026-07-28T06:21:37Z","summary":"Uncut overview donuts (percent radii) + bordered preview frame with inner margin."},{"session":"3","actor":"Marco Mendão","started":"2026-07-27T09:10:19Z","ended":"2026-07-27T09:13:23Z","summary":"Align screen preview with print: mm sheet, no vh, shared compact styles."},{"session":"2","actor":"Marco Mendão","started":"2026-07-27T08:16:53Z","ended":"2026-07-27T08:17:58Z","summary":"Week export: overview pie charts inline in one row."},{"session":"1","actor":"Marco Mendão","started":"2026-07-27T08:01:25Z","ended":"2026-07-27T08:08:01Z","summary":"Planning calendar PDF export: month listing + week landscape preview, overview metrics, print chrome, i18n, Mensal/Semana triggers."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/items/B-029-export-semana-cabecalhos-desformatados-md-x.md":{"id":"B-029","title":"Export semana — cabeçalhos desformatados quando MD-X só até meio da semana","type":"bug","status":"backlog","priority":"medium","size":"S","points":2,"estimateMinutes":55,"actualMinutes":0,"actualMs":0,"tags":["bug","planeamento","export","pdf","semana","md-x","layout"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-007","epic":"E-004","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/items/B-029-export-semana-cabecalhos-desformatados-md-x.md","description":"Na exportação da vista **semana** do planeamento, os cabeçalhos dos dias (seg, ter, qua, …) ficam desformatados quando existe um jogo a meio da semana (ex. quarta-feira). O cálculo dos match days (**MD-X**) só é aplicado até ao dia do jogo, pelo que a partir desse dia os cabeçalhos ficam mais baixos / com altura diferente e o layout parte-se.","acceptanceCriteria":[{"checked":false,"text":"Todos os cabeçalhos dos dias da semana no export têm a **mesma altura/tamanho**, com ou sem contabilização de match days (MD-X)"},{"checked":false,"text":"Dias sem MD-X reservam o mesmo espaço vertical que dias com MD-X (placeholder / altura mínima estável)"},{"checked":false,"text":"Layout dos cabeçalhos (seg–dom) permanece alinhado e formatado com jogo a meio da semana, no início ou no fim da semana, e sem jogos"},{"checked":false,"text":"Preview e PDF export reflectem o mesmo comportamento"}],"acceptanceCriteriaRaw":"- [ ] Todos os cabeçalhos dos dias da semana no export têm a **mesma altura/tamanho**, com ou sem contabilização de match days (MD-X)\n- [ ] Dias sem MD-X reservam o mesmo espaço vertical que dias com MD-X (placeholder / altura mínima estável)\n- [ ] Layout dos cabeçalhos (seg–dom) permanece alinhado e formatado com jogo a meio da semana, no início ou no fim da semana, e sem jogos\n- [ ] Preview e PDF export reflectem o mesmo comportamento","reproSteps":"1. Navegar para o planeamento\n2. Adicionar um jogo a meio da semana (ex. quarta-feira)\n3. Exportar a vista semana","fixCriteria":"- [ ] Todos os cabeçalhos dos dias da semana no export têm a **mesma altura/tamanho**, com ou sem contabilização de match days (MD-X)\n- [ ] Dias sem MD-X reservam o mesmo espaço vertical que dias com MD-X (placeholder / altura mínima estável)\n- [ ] Layout dos cabeçalhos (seg–dom) permanece alinhado e formatado com jogo a meio da semana, no início ou no fim da semana, e sem jogos\n- [ ] Preview e PDF export reflectem o mesmo comportamento","notes":"- Relacionado com [S-007](../story.md) (export PDF semana), [B-009](../../items/B-009-export-pdf-semana-omite-jogos-domingo.md), [B-024](../../items/B-024-md-x-em-falta-jogos-a-7-dias.md).\n- Hipótese: altura do cabeçalho depende da presença da label MD-X; dias sem MD-X encolhem.","promptFeedback":[{"index":"1","when":"2026-08-10T06:44:54Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task bug — export semana: cabeçalhos desformatados porque MD-X só até meio da semana (ex. jogo à quarta); todos os cabeçalhos devem ter o mesmo tamanho."}],"commits":[],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md":{"id":"S-011","title":"Mostrar meso e micro ciclos no calendário de planeamento","type":"story","status":"done","priority":"high","size":"XL","points":8,"estimateMinutes":80,"actualMinutes":317,"actualMs":19076000,"tags":["planeamento","calendar","periodizacao","meso-ciclo","micro-ciclo","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-004","epic":"E-004","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T11:29:57Z","completedAt":"2026-07-29T16:47:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md","userStory":"Como treinador, quero ver **meso ciclos** e **micro ciclos** no calendário de planeamento (vistas mensal, semana e diária), calculados a partir do primeiro treino ou jogo da época, com cores distintas e duração configurável, para orientar a periodização sem ter de criar esses blocos manualmente.","acceptanceCriteria":[{"checked":true,"text":"No módulo de planeamento são mostrados **meso ciclos** e **micro ciclos**"},{"checked":true,"text":"Por defeito: **meso ciclo** = 1 mês de trabalho; **micro ciclo** = 1 semana de trabalho"},{"checked":true,"text":"Existe um esquema de **máximo 4 cores** para diferenciar meso ciclos (e micro ciclos de forma coerente); as cores **circulam** ao chegar à última (ex.: meso 1→cor1, 2→cor2, 3→cor3, 4→cor4, 5→cor1)"},{"checked":true,"text":"A contagem de meso e micro ciclos começa no **primeiro treino ou jogo** da época (não no início civil da época)"},{"checked":true,"text":"Os ciclos aparecem como informação tipo *appointment* no calendário, mas **não são adicionáveis** pelo utilizador — são **calculados** quando o primeiro treino/jogo é adicionado"},{"checked":true,"text":"Existe cálculo **retroactivo** que coloca meso/micro ciclos para **todas as equipas/épocas** já existentes no sistema"},{"checked":true,"text":"O utilizador pode **alterar o início e o fim** de cada meso/micro ciclo (dois date pickers); ciclos podem ter **durações diferentes**; os ciclos seguintes **recalculam-se** em conformidade (durações por defeito nas definições da época)"},{"checked":true,"text":"A informação é apresentada de forma **visualmente clara e apelativa** nas vistas **mensal**, **semana** e **diária** (UX/UI cuidada, sem sobrecarregar o calendário)"},{"checked":true,"text":"No **export PDF** de planeamento (semana e mês) aparecem também meso e micro ciclos (cores + chips), alinhados com o calendário"},{"checked":true,"text":"No **relatório da unidade de treino** (cabeçalho e impressão) e no cartão **Resumo da sessão** (adicionar/editar treino) aparece o meso e micro ciclo do dia do treino"}],"acceptanceCriteriaRaw":"- [x] No módulo de planeamento são mostrados **meso ciclos** e **micro ciclos**\n- [x] Por defeito: **meso ciclo** = 1 mês de trabalho; **micro ciclo** = 1 semana de trabalho\n- [x] Existe um esquema de **máximo 4 cores** para diferenciar meso ciclos (e micro ciclos de forma coerente); as cores **circulam** ao chegar à última (ex.: meso 1→cor1, 2→cor2, 3→cor3, 4→cor4, 5→cor1)\n- [x] A contagem de meso e micro ciclos começa no **primeiro treino ou jogo** da época (não no início civil da época)\n- [x] Os ciclos aparecem como informação tipo *appointment* no calendário, mas **não são adicionáveis** pelo utilizador — são **calculados** quando o primeiro treino/jogo é adicionado\n- [x] Existe cálculo **retroactivo** que coloca meso/micro ciclos para **todas as equipas/épocas** já existentes no sistema\n- [x] O utilizador pode **alterar o início e o fim** de cada meso/micro ciclo (dois date pickers); ciclos podem ter **durações diferentes**; os ciclos seguintes **recalculam-se** em conformidade (durações por defeito nas definições da época)\n- [x] A informação é apresentada de forma **visualmente clara e apelativa** nas vistas **mensal**, **semana** e **diária** (UX/UI cuidada, sem sobrecarregar o calendário)\n- [x] No **export PDF** de planeamento (semana e mês) aparecem também meso e micro ciclos (cores + chips), alinhados com o calendário\n- [x] No **relatório da unidade de treino** (cabeçalho e impressão) e no cartão **Resumo da sessão** (adicionar/editar treino) aparece o meso e micro ciclo do dia do treino","tasksMarkdown":"","children":[],"promptFeedback":[{"index":"1","when":"2026-07-29T11:23:11Z","kind":"prompt","author":"Marco Mendão","summary":"Story: meso/micro no planeamento; defaults mês/semana; 4 cores em ciclo; âncora no 1º treino/jogo; não adicionável (calculado); backfill; duração editável com recálculo; UX mensal/semana/diária."},{"index":"2","when":"2026-07-29T11:29:57Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — implementar S-011 completa (cálculo, cores, backfill, duração editável, UX mensal/semana/diária)."},{"index":"3","when":"2026-07-29T12:24:31Z","kind":"prompt","author":"Marco Mendão","summary":"Alteração de meso/micro deve ser dois pickers de datas; permitir micro e meso com durações diferentes."},{"index":"4","when":"2026-07-29T12:29:05Z","kind":"prompt","author":"Marco Mendão","summary":"Informação sobre micro e meso ciclo também deve aparecer no export de planeamento para PDF."},{"index":"5","when":"2026-07-29T12:36:00Z","kind":"prompt","author":"Marco Mendão","summary":"Export mensal: só labels M/μ, sem barras de cor meso/micro."},{"index":"6","when":"2026-07-29T12:39:11Z","kind":"prompt","author":"Marco Mendão","summary":"Melhorar cores: distinguir meso ciclos rápido; combinação meso+micro de fácil distinção."},{"index":"7","when":"2026-07-29T12:41:16Z","kind":"prompt","author":"Marco Mendão","summary":"Retirar linhas de cor meso/micro; deixar só as legendas (chips)."},{"index":"8","when":"2026-07-29T14:02:30Z","kind":"prompt","author":"Marco Mendão","summary":"Em mobile, legenda meso/micro por baixo do dia."},{"index":"9","when":"2026-07-29T14:05:42Z","kind":"prompt","author":"Marco Mendão","summary":"Relatório unidade de treino (cabeçalho) + Resumo da sessão: indicar meso e micro ciclo do treino."},{"index":"10","when":"2026-07-29T14:42:43Z","kind":"prompt","author":"Marco Mendão","summary":"Relatório: formato Mesociclo/Microciclo com números; retirar labels M1 e μ3."},{"index":"11","when":"2026-07-29T14:48:12Z","kind":"prompt","author":"Marco Mendão","summary":"Relatório unidade de treino: preview igual ao imprimir, dentro de frame como export planeamento."},{"index":"12","when":"2026-07-29T14:53:14Z","kind":"prompt","author":"Marco Mendão","summary":"Remover logo e footer do relatório; deixar só a paginação."},{"index":"13","when":"2026-07-29T15:00:41Z","kind":"prompt","author":"Marco Mendão","summary":"Impressão sem caixa; cabeçalho: só linha em baixo; equipa+logo à esquerda; “Unidade de treino” à direita."},{"index":"14","when":"2026-07-29T15:06:19Z","kind":"prompt","author":"Marco Mendão","summary":"Cabeçalho do relatório só na primeira página."},{"index":"15","when":"2026-07-29T15:09:38Z","kind":"prompt","author":"Marco Mendão","summary":"Caixa dos jogadores deve ocupar o máximo de espaço até ao fim da página da unidade de treino."},{"index":"16","when":"2026-07-29T15:11:00Z","kind":"prompt","author":"Marco Mendão","summary":"Primeira página em branco — corrigir."},{"index":"17","when":"2026-07-29T15:14:49Z","kind":"prompt","author":"Marco Mendão","summary":"Continua a aparecer a primeira página em branco."},{"index":"18","when":"2026-07-29T15:16:48Z","kind":"prompt","author":"Marco Mendão","summary":"Bordas exercícios/jogadores iguais ao cabeçalho (cor + curvatura discreta)."},{"index":"19","when":"2026-07-29T15:19:58Z","kind":"prompt","author":"Marco Mendão","summary":"Labels Fase/Foco/Intensidade/Objetivo com a mesma cor que “Detalhes do treino”."},{"index":"20","when":"2026-07-29T15:22:25Z","kind":"prompt","author":"Marco Mendão","summary":"Por defeito o reporte de unidade de treino com 3 exercícios por página."},{"index":"21","when":"2026-07-29T15:25:25Z","kind":"prompt","author":"Marco Mendão","summary":"Mais espaçamento entre os 3 exercícios na página."},{"index":"22","when":"2026-07-29T15:27:32Z","kind":"prompt","author":"Marco Mendão","summary":"Página com 3 exercícios: centrar os exercícios na página."},{"index":"23","when":"2026-07-29T15:31:19Z","kind":"prompt","author":"Marco Mendão","summary":"Layout 3 exercícios/página: imagens a 100% do espaço, sem pedaços em branco."},{"index":"24","when":"2026-07-29T15:33:40Z","kind":"prompt","author":"Marco Mendão","summary":"Padding top/bottom na imagem do exercício."},{"index":"25","when":"2026-07-29T15:34:40Z","kind":"prompt","author":"Marco Mendão","summary":"Imagem do exercício sem corte (contain + padding)."},{"index":"26","when":"2026-07-29T15:35:57Z","kind":"prompt","author":"Marco Mendão","summary":"Bug: imagem a cores e sem cores lado a lado; default campo = sem cores."},{"index":"27","when":"2026-07-29T15:37:29Z","kind":"prompt","author":"Marco Mendão","summary":"Sem padding esquerda/direita na imagem do exercício."},{"index":"28","when":"2026-07-29T15:38:01Z","kind":"prompt","author":"Marco Mendão","summary":"Apagar label “Descrição” no cartão do exercício."},{"index":"29","when":"2026-07-29T15:40:34Z","kind":"prompt","author":"Marco Mendão","summary":"Espaços fixos para descrição/espaço/material/configuração nos cartões de exercício."},{"index":"30","when":"2026-07-29T15:43:46Z","kind":"prompt","author":"Marco Mendão","summary":"Mais espaço na descrição; espaço/material/configuração no fundo do cartão."},{"index":"31","when":"2026-07-29T15:44:58Z","kind":"prompt","author":"Marco Mendão","summary":"Descrição com line-clamp quando não cabe tudo."},{"index":"32","when":"2026-07-29T15:46:08Z","kind":"prompt","author":"Marco Mendão","summary":"Preview do relatório: versão estática dos exercícios (sem animação)."},{"index":"33","when":"2026-07-29T15:48:08Z","kind":"prompt","author":"Marco Mendão","summary":"Reduzir padding à direita da imagem para a aproximar da margem esquerda."},{"index":"34","when":"2026-07-29T15:52:19Z","kind":"prompt","author":"Marco Mendão","summary":"Menos espaço imagem↔descrição; borda esquerda a separar as duas componentes."},{"index":"35","when":"2026-07-29T15:53:47Z","kind":"prompt","author":"Marco Mendão","summary":"Aumentar largura do exercise-body; menos distância imagem↔descrição."},{"index":"36","when":"2026-07-29T16:10:29Z","kind":"prompt","author":"Marco Mendão","summary":"Descrição com máx. 8 linhas no modo 3 exercícios/página."},{"index":"37","when":"2026-07-29T16:13:01Z","kind":"prompt","author":"Marco Mendão","summary":"2 e 4 exercícios/página: mais espaçamento e centrar na página."},{"index":"38","when":"2026-07-29T16:47:53Z","kind":"feedback","author":"Marco Mendão","summary":"/complete-work — ACs verificados no código; story concluída (incl. polish do relatório + footer CoachID)."}],"commits":[{"sha":"542a135","repo":"coachid_app_frontend","date":"2026-07-29T16:47:20Z","author":"Marco Mendão","message":"add CoachID generated footer to training report"},{"sha":"8ddaecb","repo":"coachid_app_frontend","date":"2026-07-29T16:40:20Z","author":"Marco Mendão","message":"fix and enlarge 1-per-page training report layout"},{"sha":"f85f20a","repo":"coachid_app_frontend","date":"2026-07-29T16:32:17Z","author":"Marco Mendão","message":"enlarge 3-per-page cards and allow 10-line descriptions"},{"sha":"7fc17dd","repo":"coachid_app_frontend","date":"2026-07-29T16:28:10Z","author":"Marco Mendão","message":"make exercise type semi-bold in report"},{"sha":"2c29e1b","repo":"coachid_app_frontend","date":"2026-07-29T16:25:38Z","author":"Marco Mendão","message":"ease 4-per-page meta spacing above timing"},{"sha":"701f81f","repo":"coachid_app_frontend","date":"2026-07-29T16:21:40Z","author":"Marco Mendão","message":"enlarge 4-per-page exercise cards"},{"sha":"80089e6","repo":"coachid_app_frontend","date":"2026-07-29T16:19:03Z","author":"Marco Mendão","message":"tighten 4-per-page description and meta spacing"},{"sha":"430bcde","repo":"coachid_app_frontend","date":"2026-07-29T16:15:12Z","author":"Marco Mendão","message":"center and space 2 and 4 exercise pages"},{"sha":"5d61834","repo":"coachid_app_frontend","date":"2026-07-29T16:12:16Z","author":"Marco Mendão","message":"clamp training report description to 8 lines at 3 per page"},{"sha":"b949297","repo":"coachid_app_frontend","date":"2026-07-29T15:54:38Z","author":"Marco Mendão","message":"tighten training report exercise image and body split"},{"sha":"a3cba59","repo":"coachid_app_frontend","date":"2026-07-29T15:47:42Z","author":"Marco Mendão","message":"refine training report exercise card layout"},{"sha":"8c43802","repo":"coachid_app_frontend","date":"2026-07-29T15:22:10Z","author":"Marco Mendão","message":"polish training report print chrome"},{"sha":"2a43f76","repo":"coachid_app_frontend","date":"2026-07-29T14:47:29Z","author":"Marco Mendão","message":"show planning cycles on training report and summary"},{"sha":"0e00198","repo":"coachid_app_frontend","date":"2026-07-29T14:03:38Z","author":"Marco Mendão","message":"refine planning cycle labels and colours"},{"sha":"4922211","repo":"coachid_app_frontend","date":"2026-07-29T12:38:34Z","author":"Marco Mendão","message":"show planning cycles on pdf export"},{"sha":"dfbf0b8","repo":"coachid_app_frontend","date":"2026-07-29T12:28:20Z","author":"Marco Mendão","message":"edit planning cycles with date pickers"},{"sha":"0891c49","repo":"coachid_app_api","date":"2026-07-29T12:28:20Z","author":"Marco Mendão","message":"add variable planning cycle date ranges"},{"sha":"3871d02","repo":"coachid_app_frontend","date":"2026-07-29T12:14:28Z","author":"Marco Mendão","message":"add meso and micro cycle chip tooltips"},{"sha":"3649cf7","repo":"coachid_app_api","date":"2026-07-29T12:11:58Z","author":"Marco Mendão","message":"add planning meso and micro cycle API"},{"sha":"6c0ed61","repo":"coachid_app_frontend","date":"2026-07-29T12:11:58Z","author":"Marco Mendão","message":"show meso and micro cycles on planning calendar"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T11:29:57Z","ended":"2026-07-29T16:47:53Z","summary":"Implemented meso/micro cycles (calendar, PDF, report); polished training report print layouts 1–4/page; CoachID generated footer."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/epic.md":{"id":"E-005","title":"Lineup","type":"epic","status":"in_progress","priority":"medium","size":"—","points":5,"estimateMinutes":120,"actualMinutes":1,"actualMs":60000,"tags":["module","lineup"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-05T00:13:06Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/epic.md","goal":"Entregar e evoluir o módulo Lineup — composição de equipas, posições e gestão de plantéis no CoachID.","scope":"- Modelos, APIs e UI de lineup\n- Integração com outros módulos do produto quando necessário","outOfScope":"- Módulos Motor de exercícios, PSE, Wellness e Planeamento (epics próprios)","successMetrics":"- Fluxos principais de lineup utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"T-027","title":"Exportar plantel — documento estilo relatório de unidade de treino","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md"},{"id":"T-054","title":"Jogador — campos Número e Pé preferencial (lista e export lineup)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md"}],"commits":[{"sha":"25e1156","repo":"coachid-taskmark","date":"2026-07-30T23:46:05+01:00","author":"Marco Mendão","message":"add T-027 export plantel document"},{"sha":"ebfbb7c","repo":"coachid_app_frontend","date":"2026-08-05T01:31:39+01:00","author":"Marco Mendão","message":"add lineup plantel export document"},{"sha":"4a756c7","repo":"coachid-taskmark","date":"2026-08-05T00:31:39Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md":{"id":"T-027","title":"Exportar plantel — documento estilo relatório de unidade de treino","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":0,"actualMs":0,"tags":["lineup","plantel","export","pdf","report","print"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-005","epic":"E-005","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-05T00:13:06Z","completedAt":"2026-08-05T00:17:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md","description":"No módulo do **plantel** deve ser possível **exportar o plantel** como documento imprimível/PDF, visualmente alinhado com os outros documentos do sistema — referência: **relatório de unidade de treino**.","acceptanceCriteria":[{"checked":true,"text":"No módulo do plantel existe acção para **exportar** o plantel (documento / impressão / PDF conforme o padrão dos outros reports)"},{"checked":true,"text":"O documento tem **cabeçalho** com os detalhes da **equipa** e da **época** seleccionada (mesmo espírito do cabeçalho do relatório de unidade de treino)"},{"checked":true,"text":"Por baixo do cabeçalho, lista de **jogadores ordenados por posição**, à semelhança da listagem no módulo do plantel"},{"checked":true,"text":"Secção de métricas / gráficos:"},{"checked":true,"text":"Gráfico **donut cumulativo** de assiduidade: **presenças vs ausências** de todos os jogadores"},{"checked":true,"text":"Gráfico **donut** com a **quantidade de posições** no plantel"},{"checked":true,"text":"Indicadores do **número de jogos** e **número de treinos** do plantel que existem no **planeamento** para a época em questão"},{"checked":true,"text":"**Footer** igual ao do relatório de unidade de treino (`TrainingReportGeneratedFooter` / chrome de impressão correspondente)"},{"checked":true,"text":"Layout de impressão/export coerente com o sistema (preview ≈ impressão, como nos outros documentos)"}],"acceptanceCriteriaRaw":"- [x] No módulo do plantel existe acção para **exportar** o plantel (documento / impressão / PDF conforme o padrão dos outros reports)\n- [x] O documento tem **cabeçalho** com os detalhes da **equipa** e da **época** seleccionada (mesmo espírito do cabeçalho do relatório de unidade de treino)\n- [x] Por baixo do cabeçalho, lista de **jogadores ordenados por posição**, à semelhança da listagem no módulo do plantel\n- [x] Secção de métricas / gráficos:\n - [x] Gráfico **donut cumulativo** de assiduidade: **presenças vs ausências** de todos os jogadores\n - [x] Gráfico **donut** com a **quantidade de posições** no plantel\n - [x] Indicadores do **número de jogos** e **número de treinos** do plantel que existem no **planeamento** para a época em questão\n- [x] **Footer** igual ao do relatório de unidade de treino (`TrainingReportGeneratedFooter` / chrome de impressão correspondente)\n- [x] Layout de impressão/export coerente com o sistema (preview ≈ impressão, como nos outros documentos)","reproSteps":"","fixCriteria":"","notes":"Referência de implementação: relatório de unidade de treino em `(expanded)/calendar/training/[id]/report/` (documento, print chrome, footer gerado).","promptFeedback":[{"index":"1","when":"2026-07-30T22:45:36Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — export plantel documento tipo unidade de treino; cabeçalho equipa/época; jogadores por posição; donuts assiduidade e posições; nº jogos/treinos do planeamento; footer igual ao report de treino."},{"index":"2","when":"2026-08-05T00:13:06Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa esta tarefa T-027."},{"index":"3","when":"2026-08-05T00:17:14Z","kind":"feedback","author":"Marco Mendão","summary":"T-027: export plantel via /lineup/export print preview."}],"commits":[{"sha":"25e1156","repo":"coachid-taskmark","date":"2026-07-30T23:46:05+01:00","author":"Marco Mendão","message":"add T-027 export plantel document"},{"sha":"ebfbb7c","repo":"coachid_app_frontend","date":"2026-08-05T01:31:39+01:00","author":"Marco Mendão","message":"add lineup plantel export document"},{"sha":"4a756c7","repo":"coachid-taskmark","date":"2026-08-05T00:31:39Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md":{"id":"T-054","title":"Jogador — campos Número e Pé preferencial (lista e export lineup)","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["lineup","jogador","plantel","export","ui"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-005","epic":"E-005","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T00:03:29Z","completedAt":"2026-08-12T00:07:29Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md","description":"Na adição/edição do jogador, passar a existir dois campos novos:\n\n1. **Número** — número do jogador; deve aparecer na **lista de jogadores** e no **export do lineup**\n2. **Pé preferencial** — opções **direito** e **esquerdo**","acceptanceCriteria":[{"checked":true,"text":"No formulário de **adição** do jogador existem os campos Número e Pé preferencial"},{"checked":true,"text":"No formulário de **edição** do jogador os mesmos campos carregam e gravam o valor actual"},{"checked":true,"text":"Pé preferencial permite seleccionar **direito** ou **esquerdo** (i18n)"},{"checked":true,"text":"O **Número** é mostrado na lista de jogadores"},{"checked":true,"text":"O **Número** é incluído no export do lineup / plantel"},{"checked":true,"text":"Valores persistidos na API/modelo do jogador (ou entidade equivalente do plantel)"}],"acceptanceCriteriaRaw":"- [x] No formulário de **adição** do jogador existem os campos Número e Pé preferencial\n- [x] No formulário de **edição** do jogador os mesmos campos carregam e gravam o valor actual\n- [x] Pé preferencial permite seleccionar **direito** ou **esquerdo** (i18n)\n- [x] O **Número** é mostrado na lista de jogadores\n- [x] O **Número** é incluído no export do lineup / plantel\n- [x] Valores persistidos na API/modelo do jogador (ou entidade equivalente do plantel)","reproSteps":"","fixCriteria":"","notes":"Relacionado com [T-027](T-027-exportar-plantel-documento.md) (export do plantel). Confirmar se Pé preferencial também deve aparecer na lista/export ou só no formulário — o pedido exige Número na lista e no export; Pé preferencial pelo menos no formulário.","promptFeedback":[{"index":"1","when":"2026-08-10T06:37:28Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — jogador: campos Número (lista + export lineup) e Pé preferencial (direito/esquerdo) na adição/edição."},{"index":"2","when":"2026-08-12T00:03:29Z","kind":"prompt","author":"Marco Mendão","summary":"Implementa as tarefas T-051, T-052, T-053, T-054"}],"commits":[{"sha":"f1c0dd1","repo":"coachid_app_api","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"add player number and preferred foot fields"},{"sha":"1162d75","repo":"coachid_app_api (worktree-1)","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"add player number and preferred foot fields"},{"sha":"f50bae5","repo":"coachid_app_frontend","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"},{"sha":"064e451","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-12T14:41:12Z","author":"Marco Mendão","message":"ship T-051 to T-054 ui intensity and player fields"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T00:06:29Z","ended":"2026-08-12T00:07:29Z","summary":"Player number + preferred foot on form, list, export; shared-batch: 1 of 4min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/epic.md":{"id":"E-006","title":"Website","type":"epic","status":"in_progress","priority":"medium","size":"—","points":7,"estimateMinutes":70,"actualMinutes":44,"actualMs":2673000,"tags":["module","website"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:54:21Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/epic.md","goal":"Entregar e evoluir o website CoachID (marketing / site público) — conteúdo, UX, SEO e integração com o produto quando necessário.","scope":"- Site público CoachID (`coachid-site` e superfícies relacionadas)\n- Conteúdo, páginas, performance e experiências de aquisição","outOfScope":"- Módulos da app (Motor de exercícios, PSE, Wellness, Planeamento, Lineup) — epics próprios","successMetrics":"- Fluxos e páginas principais do website utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"B-004","title":"Artigos em destaque — imagem sem cover inflaciona os cartões","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md"},{"id":"T-008","title":"Artigos website — restaurar bullets de listagem (disc)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md"},{"id":"T-009","title":"Artigos website — imagens a 100% da largura do conteúdo","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md"},{"id":"T-021","title":"Hero — embed Loom com moldura responsiva","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md"},{"id":"T-057","title":"Melhorar SEO do website e da app (titles, OG, robots, schema)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md"}],"commits":[{"sha":"5fd5655","repo":"coachid-site","date":"2026-07-28T08:38:39Z","author":"Marco Mendão","message":"use local exercise video in hero"},{"sha":"447e320","repo":"coachid-site","date":"2026-07-28T08:32:10Z","author":"Marco Mendão","message":"add loom embed in hero with mockup frame"},{"sha":"b0cc6fb","repo":"coachid-site","date":"2026-07-28T08:21:16Z","author":"Marco Mendão","message":"set early adopter counter to 346"},{"sha":"e2292f3","repo":"coachid-site","date":"2026-07-28T08:17:07Z","author":"Marco Mendão","message":"set related article title height to 80px"},{"sha":"b50b735","repo":"coachid-site","date":"2026-07-28T08:14:36Z","author":"Marco Mendão","message":"fix related article title clamp ghost text"},{"sha":"1847f40","repo":"coachid-site","date":"2026-07-28T08:11:37Z","author":"Marco Mendão","message":"strengthen site-nav frosted glass blur"},{"sha":"98a68ec","repo":"coachid-site","date":"2026-07-28T08:10:05Z","author":"Marco Mendão","message":"equalize related article card heights"},{"sha":"4f48924","repo":"coachid-site","date":"2026-07-28T08:07:14Z","author":"Marco Mendão","message":"strengthen site-nav backdrop blur"},{"sha":"31158e9","repo":"coachid-site","date":"2026-07-28T07:56:14Z","author":"Marco Mendão","message":"fix article lists images and featured cover"},{"sha":"ba76147","repo":"coachid-taskmark","date":"2026-07-23T07:25:56+01:00","author":"Marco Mendão","message":"update taskmark board"}],"workLog":[{"session":"4","actor":"Marco Mendão","started":"2026-07-28T08:14:36Z","ended":"2026-07-28T08:14:36Z","summary":"Fix related title clamp ghost text."},{"session":"3","actor":"Marco Mendão","started":"2026-07-28T08:11:37Z","ended":"2026-07-28T08:11:37Z","summary":"Stronger site-nav frosted glass (56px blur)."},{"session":"2","actor":"Marco Mendão","started":"2026-07-28T08:06:58Z","ended":"2026-07-28T08:07:14Z","summary":"Stronger translucent site-nav backdrop blur."},{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:54:21Z","ended":"2026-07-28T07:54:21Z","summary":"Parent rollup (0ms); billable on T-008/T-009/B-004."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md":{"id":"B-004","title":"Artigos em destaque — imagem sem cover inflaciona os cartões","type":"bug","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":1,"actualMs":69000,"tags":["website","blog","featured","images","cover","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-006","epic":"E-006","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:54:21Z","completedAt":"2026-07-28T07:56:39Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md","description":"Nos artigos em destaque do blog, a imagem não está em formato **cover**. Com aspect ratios desfavoráveis (ex.: 9:16), os cartões ficam excessivamente altos. A imagem deve ocupar apenas o essencial para enquadrar título e subtítulo do artigo (área de media com altura/ratio controlados e `object-fit: cover` ou equivalente).","acceptanceCriteria":[{"checked":true,"text":"Imagens dos cartões de artigos em destaque usam comportamento **cover** (preenchem a área sem distorcer o cartão)"},{"checked":true,"text":"A área da imagem tem dimensão estável / essencial para título e subtítulo (não cresce com o aspect ratio da foto)"},{"checked":true,"text":"Aspect ratios extremos (ex.: 9:16) não inflam os cartões"},{"checked":true,"text":"Título e subtítulo continuam legíveis e bem compostos no cartão"}],"acceptanceCriteriaRaw":"- [x] Imagens dos cartões de artigos em destaque usam comportamento **cover** (preenchem a área sem distorcer o cartão)\n- [x] A área da imagem tem dimensão estável / essencial para título e subtítulo (não cresce com o aspect ratio da foto)\n- [x] Aspect ratios extremos (ex.: 9:16) não inflam os cartões\n- [x] Título e subtítulo continuam legíveis e bem compostos no cartão","reproSteps":"1. Abrir a área de artigos em destaque do blog\n2. Usar (ou observar) um artigo cuja imagem tenha aspect ratio vertical mau (ex.: 9:16)\n3. Verificar que o cartão fica demasiado grande / alto em vez de manter altura estável com crop cover","fixCriteria":"- [x] Imagens dos cartões de artigos em destaque usam comportamento **cover** (preenchem a área sem distorcer o cartão)\n- [x] A área da imagem tem dimensão estável / essencial para título e subtítulo (não cresce com o aspect ratio da foto)\n- [x] Aspect ratios extremos (ex.: 9:16) não inflam os cartões\n- [x] Título e subtítulo continuam legíveis e bem compostos no cartão","notes":"General bug no epic E-006 Website.","promptFeedback":[{"index":"4","when":"2026-07-28T08:05:36Z","kind":"prompt","author":"Marco Mendão","summary":"Featured card still showed empty band; cover must fill media column."},{"index":"5","when":"2026-07-28T08:05:36Z","kind":"feedback","author":"Marco Mendão","summary":"Media box stretch + absolute cover fill."},{"index":"3","when":"2026-07-28T07:56:39Z","kind":"feedback","author":"Marco Mendão","summary":"Delivered in E-006 batch."},{"index":"2","when":"2026-07-28T07:54:21Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar com batch E-006."},{"index":"1","when":"2026-07-23T06:19:44Z","kind":"prompt","author":"Marco Mendão","summary":"Blog featured: imagem sem cover; cartões grandes com aspect ratio mau (9:16); imagem só o essencial p/ título+subtítulo."}],"commits":[{"sha":"9af0467","repo":"coachid-site","date":"2026-07-28T08:05:36Z","author":"Marco Mendão","message":"fill blog card images with object-fit cover"},{"sha":"31158e9","repo":"coachid-site","date":"2026-07-28T07:56:14Z","author":"Marco Mendão","message":"fix article lists images and featured cover"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:54:21Z","ended":"2026-07-28T07:55:30Z","summary":"Featured cards use cover aspect ratio. shared-batch: 69197 of 138393ms by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md":{"id":"T-008","title":"Artigos website — restaurar bullets de listagem (disc)","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"tags":["website","artigos","css","lists","typography"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-006","epic":"E-006","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:54:21Z","completedAt":"2026-07-28T07:56:39Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md","description":"Nas listagens (listas) dentro dos artigos do website, falta o marcador de listagem habitual (`list-style: disc` / bullets). Corrigir o estilo para que as listas mostrem o ponto de listagem como é costume.","acceptanceCriteria":[{"checked":true,"text":"Listas não ordenadas nos artigos do website mostram bullets (`disc`)"},{"checked":true,"text":"Estilo consistente com o aspecto esperado de listagens em conteúdo editorial"},{"checked":true,"text":"Verificado em artigos com listas (desktop e mobile)"}],"acceptanceCriteriaRaw":"- [x] Listas não ordenadas nos artigos do website mostram bullets (`disc`)\n- [x] Estilo consistente com o aspecto esperado de listagens em conteúdo editorial\n- [x] Verificado em artigos com listas (desktop e mobile)","reproSteps":"","fixCriteria":"","notes":"General task no epic E-006 Website.","promptFeedback":[{"index":"3","when":"2026-07-28T07:56:39Z","kind":"feedback","author":"Marco Mendão","summary":"Delivered in E-006 batch."},{"index":"2","when":"2026-07-28T07:54:21Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar com batch E-006."},{"index":"1","when":"2026-07-23T06:10:26Z","kind":"prompt","author":"Marco Mendão","summary":"Artigos website: listagens sem ponto/disc — corrigir para mostrar bullets habituais."}],"commits":[{"sha":"31158e9","repo":"coachid-site","date":"2026-07-28T07:56:14Z","author":"Marco Mendão","message":"fix article lists images and featured cover"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:54:21Z","ended":"2026-07-28T07:54:55Z","summary":"Restore article list disc bullets. shared-batch: 34598 of 138393ms by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md":{"id":"T-009","title":"Artigos website — imagens a 100% da largura do conteúdo","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":34000,"tags":["website","artigos","images","css"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-006","epic":"E-006","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:54:21Z","completedAt":"2026-07-28T07:56:39Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md","description":"No conteúdo dos artigos do website, todas as imagens devem ocupar **100% da largura** do conteúdo do artigo (full-width dentro da coluna do artigo), mesmo que isso implique perda de qualidade visual (upscale).","acceptanceCriteria":[{"checked":true,"text":"Imagens no corpo do artigo renderizam a 100% da largura da área de conteúdo do artigo"},{"checked":true,"text":"Imagens mais estreitas que o content width são esticadas para preencher (aceite perda de qualidade)"},{"checked":true,"text":"Comportamento consistente em desktop e mobile"},{"checked":true,"text":"Não rebenta o layout (sem overflow horizontal)"}],"acceptanceCriteriaRaw":"- [x] Imagens no corpo do artigo renderizam a 100% da largura da área de conteúdo do artigo\n- [x] Imagens mais estreitas que o content width são esticadas para preencher (aceite perda de qualidade)\n- [x] Comportamento consistente em desktop e mobile\n- [x] Não rebenta o layout (sem overflow horizontal)","reproSteps":"","fixCriteria":"","notes":"General task no epic E-006 Website.","promptFeedback":[{"index":"3","when":"2026-07-28T07:56:39Z","kind":"feedback","author":"Marco Mendão","summary":"Delivered in E-006 batch."},{"index":"2","when":"2026-07-28T07:54:21Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar com batch E-006."},{"index":"1","when":"2026-07-23T06:11:02Z","kind":"prompt","author":"Marco Mendão","summary":"Artigos: todas as imagens a 100% da largura do artigo, mesmo com perda de qualidade."}],"commits":[{"sha":"31158e9","repo":"coachid-site","date":"2026-07-28T07:56:14Z","author":"Marco Mendão","message":"fix article lists images and featured cover"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:54:21Z","ended":"2026-07-28T07:54:55Z","summary":"Article body images 100% width. shared-batch: 34598 of 138393ms by points."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md":{"id":"T-021","title":"Hero — embed Loom com moldura responsiva","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":54000,"tags":["website","hero"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-006","epic":"E-006","created":"2026-07-28","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T08:31:28Z","completedAt":"2026-07-28T08:32:22Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md","description":"Substituir a imagem do hero por um vídeo Loom embebido, com moldura (frame) alinhada ao design do site, encaixando bem com título e subtítulo em desktop e mobile.","acceptanceCriteria":[{"checked":true,"text":"Hero mostra o embed Loom (`d0020ba099294cf9af437f3c7935f6b8`)"},{"checked":true,"text":"Vídeo tem moldura/frame coerente com o resto do site"},{"checked":true,"text":"Layout encaixa com título/subtítulo/CTAs em desktop e mobile"},{"checked":true,"text":"Iframe acessível (title) e fullscreen permitido"}],"acceptanceCriteriaRaw":"- [x] Hero mostra o embed Loom (`d0020ba099294cf9af437f3c7935f6b8`)\n- [x] Vídeo tem moldura/frame coerente com o resto do site\n- [x] Layout encaixa com título/subtítulo/CTAs em desktop e mobile\n- [x] Iframe acessível (title) e fullscreen permitido","reproSteps":"","fixCriteria":"","notes":"Local `/video/exercise.mp4` (1200×800), autoplay muted loop.","promptFeedback":[{"index":"3","when":"2026-07-28T08:38:40Z","kind":"prompt","author":"Marco Mendão","summary":"Usar exercise.mp4 local em vez do Loom."},{"index":"4","when":"2026-07-28T08:38:40Z","kind":"feedback","author":"Marco Mendão","summary":"Hero usa /video/exercise.mp4 autoplay muted loop."},{"index":"2","when":"2026-07-28T08:32:22Z","kind":"feedback","author":"Marco Mendão","summary":"Hero Loom entregue com moldura mockup responsiva."},{"index":"1","when":"2026-07-28T08:31:28Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar Loom embed no hero com moldura, encaixe com título/subtítulo."}],"commits":[{"sha":"5fd5655","repo":"coachid-site","date":"2026-07-28T08:38:39Z","author":"Marco Mendão","message":"use local exercise video in hero"},{"sha":"447e320","repo":"coachid-site","date":"2026-07-28T08:32:10Z","author":"Marco Mendão","message":"add loom embed in hero with mockup frame"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T08:31:28Z","ended":"2026-07-28T08:32:22Z","summary":"Hero Loom embed with mockup frame."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md":{"id":"T-057","title":"Melhorar SEO do website e da app (titles, OG, robots, schema)","type":"task","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":41,"actualMs":2482000,"tags":["seo","metadata","opengraph","website","frontend","robots","accessibility"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-006","epic":"E-006","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:09:31Z","completedAt":"2026-08-11T16:50:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md","description":"Melhorar SEO e metadados em **coachid-site** e **coachid_app_frontend**, com base na auditoria de 2026-08-10.\n\nProblemas confirmados:\n- Na app, quase todas as rotas (~80) herdam só o título default **\"CoachID\"** — não há `generateMetadata` / `metadata` por página (excepto `/pricing` e `~offline`). O `PageHeaderContext` actualiza o header da UI, **não** o `document.title`.\n- OG/Twitter da app apontam para `brain.coachidapp.com/images/banner.png` e `app.coachidapp.com/images/banner.png` (**`banner.png` inexistente**); existe `public/og.png` (1200×630) **não referenciado**.\n- App sem `robots.ts` / `sitemap.ts` — rotas autenticadas podem ser indexadas por omissão.\n- Site já tem boa base (metadata, OG dinâmico, sitemap, robots, JSON-LD, hreflang); faltam alts em capas de artigos, schema extra e alinhamento do `og.png` estático.\n- Favicons site/app estão correctos e idênticos; `public/favicon/site.webmanifest` na app desalinhado do `manifest.ts` (theme `#1E3FFF` vs `#0E1012`).\n- Naming inconsistente: site **\"Coach ID\"** vs PWA **\"CoachID\"**.\n\nTrabalho relacionado (não duplicar às cegas):\n- [T-055](../../E-009-general/items/T-055-open-graph-og-png-site-e-app.md) — ligar `og.png` como `og:image` (site + app)\n- [T-056](../../E-009-general/items/T-056-google-analytics-app-e-site.md) — gtag (fora do scope SEO puro)\n\nRepos: `coachid-site`, `coachid_app_frontend`.","acceptanceCriteria":[{"checked":true,"text":"Layouts/páginas principais da app exportam `title` (ou `generateMetadata`) usando o template `%s — CoachID` (ex.: Calendário, Plantel, Exercícios, PSE, Wellness, Billing, Settings, Admin, Onboarding/Setup)"},{"checked":true,"text":"Páginas públicas (`/pub/rpe/...`, `/pub/.../wellness/...`, editor público) têm título descritivo"},{"checked":true,"text":"Existe `robots.ts`: indexar superfícies públicas de marketing (ex. `/pricing`); `noindex`/disallow para área autenticada e admin"},{"checked":true,"text":"Metadata root deixa de apontar para `banner.png` / `brain.coachidapp.com`; OG/Twitter usam URL absoluta válida de `og.png` (ou equivalente alinhado com T-055)"},{"checked":true,"text":"Capas de artigos (lista, detalhe, CTA) usam `alt` descritivo (ex. título do artigo), não `alt=\"\"`"},{"checked":true,"text":"JSON-LD adicional na landing: pelo menos `SoftwareApplication` e/ou `FAQPage` quando o conteúdo FAQ existir na página"},{"checked":true,"text":"`og.png` estático está ligado **ou** documentado/removido se o `opengraph-image` dinâmico for a fonte de verdade (coordenar com T-055)"},{"checked":true,"text":"Sitemap continua a incluir home + artigos pt/en; rever se há rotas estáticas novas a incluir"},{"checked":true,"text":"Favicons/manifest PWA coerentes (`manifest.ts` vs `public/favicon/site.webmanifest` — alinhar ou remover o estático obsoleto)"},{"checked":true,"text":"Naming da marca alinhado onde aparece em metadata (`Coach ID` vs `CoachID`) — decisão única aplicada"},{"checked":true,"text":"Verificar partilha (Facebook/Twitter debugger ou preview) com imagem 1200×630 correcta no site e na app"},{"checked":false,"text":"Conteúdo editorial novo (mais landing pages / blog posts) — opcional futuro"},{"checked":false,"text":"Google Analytics — ver T-056"}],"acceptanceCriteriaRaw":"### App — títulos e indexação\n- [x] Layouts/páginas principais da app exportam `title` (ou `generateMetadata`) usando o template `%s — CoachID` (ex.: Calendário, Plantel, Exercícios, PSE, Wellness, Billing, Settings, Admin, Onboarding/Setup)\n- [x] Páginas públicas (`/pub/rpe/...`, `/pub/.../wellness/...`, editor público) têm título descritivo\n- [x] Existe `robots.ts`: indexar superfícies públicas de marketing (ex. `/pricing`); `noindex`/disallow para área autenticada e admin\n- [x] Metadata root deixa de apontar para `banner.png` / `brain.coachidapp.com`; OG/Twitter usam URL absoluta válida de `og.png` (ou equivalente alinhado com T-055)\n\n### Site — SEO de conteúdo\n- [x] Capas de artigos (lista, detalhe, CTA) usam `alt` descritivo (ex. título do artigo), não `alt=\"\"`\n- [x] JSON-LD adicional na landing: pelo menos `SoftwareApplication` e/ou `FAQPage` quando o conteúdo FAQ existir na página\n- [x] `og.png` estático está ligado **ou** documentado/removido se o `opengraph-image` dinâmico for a fonte de verdade (coordenar com T-055)\n- [x] Sitemap continua a incluir home + artigos pt/en; rever se há rotas estáticas novas a incluir\n\n### Assets / consistência\n- [x] Favicons/manifest PWA coerentes (`manifest.ts` vs `public/favicon/site.webmanifest` — alinhar ou remover o estático obsoleto)\n- [x] Naming da marca alinhado onde aparece em metadata (`Coach ID` vs `CoachID`) — decisão única aplicada\n- [x] Verificar partilha (Facebook/Twitter debugger ou preview) com imagem 1200×630 correcta no site e na app\n\n### Fora de scope (nesta tarefa)\n- [ ] Conteúdo editorial novo (mais landing pages / blog posts) — opcional futuro\n- [ ] Google Analytics — ver T-056","reproSteps":"","fixCriteria":"","notes":"Prioridade sugerida de implementação:\n1. Corrigir OG da app + robots\n2. Titles por layouts da app\n3. Alts + schema no site\n4. Manifest / naming\n\nBrand naming: app/PWA metadata = **CoachID**; marketing site + copy = **Coach ID**.\n\nFavicons actuais (CID branco em `#1E3FFF`, ico/svg/96/apple/192/512) estão OK — não regenerar sem necessidade. `logo-coachid-mark.png` (12×12) é demasiado pequeno se for usado como logo visível.\n\nVerificação 2026-08-11: código aponta para `og.png` 1200×630 (app + site via T-055). Produção ainda pode devolver 404 (app) ou redirect Apache antigo (site `/og.png` → `/blog/og.png`) até ao próximo deploy — re-scrape no Facebook Debugger depois.","promptFeedback":[{"index":"3","when":"2026-08-11T16:48:58Z","kind":"prompt","author":"Marco Mendão","summary":"Verificar se T-057 está terminada (em paralelo com T-055/T-056)."},{"index":"2","when":"2026-08-11T16:09:31Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-057 na worktree-1 (SEO app+site)."},{"index":"1","when":"2026-08-10T07:06:52Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — tarefa com tudo o necessário para melhorar SEO do website e da app (titles em falta, OG, robots, schema, assets)."}],"commits":[{"sha":"c3cf8e2","repo":"coachid_app_frontend","date":"2026-08-11T16:16:38Z","author":"Marco Mendão","message":"improve app seo titles og and robots"},{"sha":"825c1d9","repo":"coachid-site","date":"2026-08-11T16:16:38Z","author":"Marco Mendão","message":"improve site seo alts and json-ld"},{"sha":"7fe6ac7","repo":"coachid_app_frontend","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"fix og.png metadata and app analytics id"},{"sha":"693561b","repo":"coachid-site","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"use og.png for default open graph image"},{"sha":"0e45c22","repo":"coachid-taskmark","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:09:31Z","ended":"2026-08-11T16:50:53Z","summary":"SEO titles/OG/robots/schema; closed remaining share-preview AC (code verified; re-scrape after deploy)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/epic.md":{"id":"E-007","title":"Admin dashboard","type":"epic","status":"done","priority":"medium","size":"—","points":39,"estimateMinutes":1315,"actualMinutes":1761,"actualMs":105691000,"tags":["module","admin","dashboard"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/epic.md","goal":"Entregar e evoluir o Admin dashboard CoachID — gestão operacional, configuração e ferramentas administrativas da plataforma.","scope":"- UI e fluxos do painel de administração\n- Operações de suporte, configuração e monitorização administrativa","outOfScope":"- Módulos de produto da app (Motor de exercícios, PSE, Wellness, Planeamento, Lineup) e Website — epics próprios","successMetrics":"- Fluxos principais de administração utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"S-008","title":"CRUD de tags e categorias dos artigos do website no admin","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md"},{"id":"S-009","title":"Gerir autores de blog posts no admin (incluindo autores manuais)","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md"},{"id":"S-010","title":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md"},{"id":"B-034","title":"Resposta admin fecha ticket em vez de passar a Em progresso","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md"}],"commits":[{"sha":"47754c4","repo":"coachid-taskmark","date":"2026-07-31T00:21:45+01:00","author":"Marco Mendão","message":"add T-031 blog author description"},{"sha":"aa39784","repo":"coachid_app_frontend","date":"2026-07-29T10:26:41Z","author":"Marco Mendão","message":"add admin article categories and tags pages"},{"sha":"fc269d9","repo":"coachid_app_api","date":"2026-07-29T10:26:41Z","author":"Marco Mendão","message":"add article tags and categories admin crud"},{"sha":"b4c0c4a","repo":"coachid-taskmark","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"526a73d","repo":"coachid_app_frontend","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"narrow admin users teams and accounts columns"},{"sha":"74615c2","repo":"coachid-taskmark","date":"2026-07-27T08:45:12+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"be8632d","repo":"coachid_app_frontend","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user metrics and dialog actions"},{"sha":"9455f17","repo":"coachid_app_api","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user team metrics"},{"sha":"d98f5aa","repo":"coachid-taskmark","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add S-010 admin users list story"},{"sha":"e2dca42","repo":"coachid_app_frontend","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"df8f10a","repo":"coachid_app_api","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add admin users list endpoint"},{"sha":"ba76147","repo":"coachid-taskmark","date":"2026-07-23T07:25:56+01:00","author":"Marco Mendão","message":"update taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T07:42:00Z","ended":"2026-07-29T07:42:00Z","summary":"End cascade: all stories done (S-008, S-009, S-010); 0-min rollup"},{"session":"2","actor":"Marco Mendão","started":"2026-08-11T16:08:09Z","ended":"2026-08-11T16:08:09Z","summary":"rollup: all children done (S-008, S-009, S-010, B-034)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md":{"id":"B-034","title":"Resposta admin fecha ticket em vez de passar a Em progresso","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":204000,"tags":["admin","support","tickets"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-007","epic":"E-007","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T11:12:23Z","completedAt":"2026-08-11T11:15:47Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md","description":"No dashboard de suporte (admin), ao responder a um ticket aberto a mensagem chega ao cliente, mas o ticket passa automaticamente para **fechado** em vez de **Em progresso**. O fecho automático só deve ocorrer após 7 dias de inactividade num ticket em progresso.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"1. Ir ao dashboard de suporte como admin\n2. Abrir um ticket que esteja aberto\n3. Responder ao ticket","fixCriteria":"","notes":"Causa: `SupportTicketsService.addAdminMessage` define `in_progress` e de seguida fecha de imediato quando `!hasUserReplyAfterLastAdminMessage` (sempre verdade logo após a resposta admin).\n\nFix: removido o fecho imediato em `addAdminMessage`; `processTicketInactivity` fecha só tickets `in_progress` após `SUPPORT_TICKET_INACTIVITY_DAYS` (default 7).","promptFeedback":[{"index":"1","when":"2026-08-11T11:12:23Z","kind":"prompt","author":"Marco Mendão","summary":"Criar bug: resposta admin fecha ticket; esperado Em progresso + fecho automático aos 7 dias; resolver de seguida"},{"index":"2","when":"2026-08-11T11:15:47Z","kind":"feedback","author":"Marco Mendão","summary":"Fix aplicado em addAdminMessage + job de inactividade restrito a in_progress"}],"commits":[{"sha":"addc25d","repo":"coachid_app_api","date":"2026-08-11T15:00:10Z","author":"Marco Mendão","message":"fix support ticket stay in progress on admin reply"},{"sha":"e06731b","repo":"coachid_app_api","date":"2026-08-11T15:00:11Z","author":"Marco Mendão","message":"fix support ticket stay in progress on admin reply"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T11:12:23Z","ended":"2026-08-11T11:15:47Z","summary":"Fixed admin reply → in_progress; inactivity auto-close after 7d"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md":{"id":"S-008","title":"CRUD de tags e categorias dos artigos do website no admin","type":"story","status":"done","priority":"medium","size":"L","points":5,"estimateMinutes":25,"actualMinutes":480,"actualMs":28800000,"tags":["admin","website","tags","categorias","artigos","crud"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-007","epic":"E-007","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T08:42:18Z","completedAt":"2026-07-29T07:41:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md","userStory":"Como administrador, quero gerir (criar, editar, listar e apagar) as **tags** e **categorias** dos artigos do website no Admin dashboard, ver quantos artigos usam cada uma, e ao apagar remover essa associação dos artigos afectados.","acceptanceCriteria":[{"checked":true,"text":"CRUD completo de **tags** de artigos do website no Admin dashboard"},{"checked":true,"text":"CRUD completo de **categorias** de artigos do website no Admin dashboard"},{"checked":true,"text":"Na listagem de tags, cada tag mostra um **contador** de artigos que a utilizam"},{"checked":true,"text":"Na listagem de categorias, cada categoria mostra um **contador** de artigos que a utilizam"},{"checked":true,"text":"Ao **apagar** uma tag, todos os artigos que a tinham ficam **sem essa tag**"},{"checked":true,"text":"Ao **apagar** uma categoria, todos os artigos que a tinham ficam **sem essa categoria**"},{"checked":true,"text":"Operações de apagar confirmadas / seguras (sem apagar os artigos em si)"}],"acceptanceCriteriaRaw":"- [x] CRUD completo de **tags** de artigos do website no Admin dashboard\n- [x] CRUD completo de **categorias** de artigos do website no Admin dashboard\n- [x] Na listagem de tags, cada tag mostra um **contador** de artigos que a utilizam\n- [x] Na listagem de categorias, cada categoria mostra um **contador** de artigos que a utilizam\n- [x] Ao **apagar** uma tag, todos os artigos que a tinham ficam **sem essa tag**\n- [x] Ao **apagar** uma categoria, todos os artigos que a tinham ficam **sem essa categoria**\n- [x] Operações de apagar confirmadas / seguras (sem apagar os artigos em si)","tasksMarkdown":"","children":[],"promptFeedback":[{"index":"5","when":"2026-07-29T07:41:30Z","kind":"prompt","author":"Marco Mendão","summary":"Continuar S-008: FE categories/tags pages, nav, actions/fetch, i18n (worktree-1)."},{"index":"4","when":"2026-07-29T07:35:02Z","kind":"prompt","author":"Marco Mendão","summary":"Port article tags/categories admin CRUD from develop API into worktree-1 API."},{"index":"3","when":"2026-07-29T07:27:25Z","kind":"prompt","author":"Marco Mendão","summary":"/implementa S-008 — CRUD tags e categorias no admin (worktree-1)."},{"index":"1","when":"2026-07-23T06:08:27Z","kind":"prompt","author":"Marco Mendão","summary":"Admin: CRUD tags e categorias dos artigos do website; contador de uso na listagem; ao apagar, remover associação dos artigos."},{"index":"2","when":"2026-07-28T08:42:18Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work S-008 e S-009 — implementar estas features."}],"commits":[{"sha":"aa39784","repo":"coachid_app_frontend","date":"2026-07-29T10:26:41Z","author":"Marco Mendão","message":"add admin article categories and tags pages"},{"sha":"fc269d9","repo":"coachid_app_api","date":"2026-07-29T10:26:41Z","author":"Marco Mendão","message":"add article tags and categories admin crud"},{"sha":"58aba78","repo":"coachid_app_frontend","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"add admin article authors and taxonomy"},{"sha":"77ccddc","repo":"coachid_app_api","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"add article author and tag schemas"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T08:42:18Z","ended":"2026-07-29T07:41:30Z","summary":"Ported API taxonomy CRUD; admin pages /categories and /tags with search, counts, confirm delete; sidebar nav"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md":{"id":"S-009","title":"Gerir autores de blog posts no admin (incluindo autores manuais)","type":"story","status":"done","priority":"medium","size":"XL","points":12,"estimateMinutes":705,"actualMinutes":706,"actualMs":42366000,"tags":["admin","website","blog","autores"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-007","epic":"E-007","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T08:42:18Z","completedAt":"2026-08-10T05:54:44.000Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md","userStory":"Como administrador, quero adicionar e gerir autores de blog posts no dashboard de administração — incluindo pessoas que **não** são utilizadores do sistema — para os atribuir aos artigos. A listagem deve mostrar os autores actuais (administradores) e os autores adicionados manualmente; na criação de artigos, esses autores também devem aparecer listados.","acceptanceCriteria":[{"checked":true,"text":"No admin é possível adicionar novos autores de blog posts"},{"checked":true,"text":"Autores manuais podem existir sem ser utilizadores do sistema"},{"checked":true,"text":"A listagem de autores mostra os autores actuais (administradores) **e** os autores adicionados manualmente"},{"checked":true,"text":"Na criação (e edição) de artigos, a lista de autores inclui administradores e autores manuais"},{"checked":true,"text":"É possível seleccionar um autor manual ao criar/editar um artigo"}],"acceptanceCriteriaRaw":"- [x] No admin é possível adicionar novos autores de blog posts\n- [x] Autores manuais podem existir sem ser utilizadores do sistema\n- [x] A listagem de autores mostra os autores actuais (administradores) **e** os autores adicionados manualmente\n- [x] Na criação (e edição) de artigos, a lista de autores inclui administradores e autores manuais\n- [x] É possível seleccionar um autor manual ao criar/editar um artigo","tasksMarkdown":"- [x] T-023 Port manual article author CRUD API to worktree-1\n- [x] T-024 Admin sidebar submenu for article authors\n- [x] T-025 Author photo file upload to S3\n- [x] T-026 Authors table UI parity + text search\n- [x] [T-031](items/T-031-editar-descricao-autor-blog.md) — Editar descrição do autor do blog (manual e utilizador) e mostrar no site","children":[{"id":"T-023","title":"Port manual article author CRUD API to worktree-1","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-023-port-author-crud-worktree-1-api.md"},{"id":"T-024","title":"Admin sidebar submenu for article authors","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-024-admin-sidebar-article-authors.md"},{"id":"T-025","title":"Author photo file upload to S3","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-025-author-photo-s3-upload.md"},{"id":"T-026","title":"Authors table UI parity + text search","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-026-authors-table-ui-search.md"},{"id":"T-031","title":"Editar descrição do autor do blog (manual e utilizador) e mostrar no site","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-031-editar-descricao-autor-blog.md"}],"promptFeedback":[{"index":"10","when":"2026-08-10T05:54:44Z","kind":"prompt","author":"Marco Mendão","summary":"implementa a tarefa S-009"},{"index":"11","when":"2026-08-10T05:54:44Z","kind":"feedback","author":"Marco Mendão","summary":"S-009 completa: T-023–T-026 + T-031 (descrição autor) entregues."},{"index":"8","when":"2026-07-29T07:04:46Z","kind":"prompt","author":"Marco Mendão","summary":"Tabela de autores similar à de artigos + pesquisa por texto."},{"index":"7","when":"2026-07-29T07:00:18Z","kind":"prompt","author":"Marco Mendão","summary":"Foto do autor: file input + guardar no S3."},{"index":"6","when":"2026-07-29T06:55:45Z","kind":"prompt","author":"Marco Mendão","summary":"Adiciona submenu na sidebar para autores nos artigos (worktree-1)."},{"index":"5","when":"2026-07-29T06:53:55Z","kind":"prompt","author":"Marco Mendão","summary":"Port author CRUD from develop API into worktree-1 (author-only)."},{"index":"1","when":"2026-07-23T06:22:43Z","kind":"prompt","author":"Marco Mendão","summary":"Admin: adicionar autores de blog (não precisam ser users); listagem = admins + manuais; na criação de artigos também aparecem."},{"index":"2","when":"2026-07-28T08:42:18Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work S-008 e S-009 — implementar estas features."},{"index":"3","when":"2026-07-29T06:18:59Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work S-009 — implementar gestão de autores de blog (manuais + admins)."},{"index":"4","when":"2026-07-29T06:19:16Z","kind":"feedback","author":"Marco Mendão","summary":"Feature já na develop (58aba78 / 77ccddc). AC verificados; story fechada."},{"index":"9","when":"2026-07-29T10:38:42Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work check: AC + T-023–T-026 done; closed open task sessions."}],"commits":[{"sha":"8635482","repo":"coachid_app_api","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"add blog author description api"},{"sha":"476a848","repo":"coachid_app_frontend","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"add author description admin ui"},{"sha":"99a826f","repo":"coachid-site","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"show author description on post byline"},{"sha":"47754c4","repo":"coachid-taskmark","date":"2026-07-31T00:21:45+01:00","author":"Marco Mendão","message":"add T-031 blog author description"},{"sha":"6e0eb89","repo":"coachid_app_api","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add article author crud and picture proxy"},{"sha":"17934eb","repo":"coachid_app_frontend","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add admin authors page and picture proxy"},{"sha":"b05ac7b","repo":"coachid-site","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"proxy article author pictures"},{"sha":"d327762","repo":"coachid_app_frontend","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"guard article form missing translations"},{"sha":"58aba78","repo":"coachid_app_frontend","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"add admin article authors and taxonomy"},{"sha":"77ccddc","repo":"coachid_app_api","date":"2026-07-28T09:30:52Z","author":"Marco Mendão","message":"add article author and tag schemas"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T06:19:16Z","ended":"2026-07-29T06:19:16Z","summary":"Verified AC already on develop (authors CRUD + article form); closed S-009"},{"session":"2","actor":"Marco Mendão","started":"2026-08-10T05:54:44Z","ended":"2026-08-10T05:54:44Z","summary":"Rollup: S-009 done after T-031 (0min; effort on children)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-023-port-author-crud-worktree-1-api.md":{"id":"T-023","title":"Port manual article author CRUD API to worktree-1","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":190000,"tags":["admin","website","blog","autores","api"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-009","epic":"E-007","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T06:50:45Z","completedAt":"2026-07-29T06:53:55Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-023-port-author-crud-worktree-1-api.md","description":"Port manual blog article author CRUD from develop `coachid_app_api` into `worktree-1/coachid_app_api` without copying tag CRUD or other develop-only taxonomy differences.","acceptanceCriteria":[{"checked":true,"text":"ArticleAuthorFeature registered in database.module"},{"checked":true,"text":"Author DTOs and factory helpers present in articles.factory"},{"checked":true,"text":"Service supports list/manage/create/update/delete authors + manual resolve"},{"checked":true,"text":"Admin controller exposes author manage routes before Get(':id')"}],"acceptanceCriteriaRaw":"- [x] ArticleAuthorFeature registered in database.module\n- [x] Author DTOs and factory helpers present in articles.factory\n- [x] Service supports list/manage/create/update/delete authors + manual resolve\n- [x] Admin controller exposes author manage routes before Get(':id')","reproSteps":"","fixCriteria":"","notes":"Schema already at worktree-1/.../database/schemas/article-author.schema.ts","promptFeedback":[{"index":"1","when":"2026-07-29T06:50:45Z","kind":"prompt","author":"Marco Mendão","summary":"Port manual blog article author CRUD from develop API into worktree-1 API (author-only)."},{"index":"2","when":"2026-07-29T06:53:55Z","kind":"feedback","author":"Marco Mendão","summary":"Author CRUD ported to worktree-1 API; tag taxonomy left unchanged."}],"commits":[{"sha":"6e0eb89","repo":"coachid_app_api","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add article author crud and picture proxy"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T06:50:45Z","ended":"2026-07-29T06:53:55Z","summary":"Ported author CRUD from develop into worktree-1 API (module, factory, service, admin routes)."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-024-admin-sidebar-article-authors.md":{"id":"T-024","title":"Admin sidebar submenu for article authors","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":55,"actualMinutes":55,"actualMs":3344000,"tags":["admin","website","blog","autores","frontend"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-009","epic":"E-007","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T06:55:45Z","completedAt":"2026-07-29T10:38:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-024-admin-sidebar-article-authors.md","description":"Add an Articles submenu in the admin sidebar with links to all articles and authors. Dedicated `/admin/articles/authors` page so the route does not fall through to `[articleId]` (which caused a 500).","acceptanceCriteria":[{"checked":true,"text":"Admin sidebar Articles expands with “All articles” and “Authors”"},{"checked":true,"text":"`/admin/articles/authors` is a static route (not `[articleId]`)"},{"checked":true,"text":"Authors management page loads without crashing"},{"checked":true,"text":"Nav / page i18n (EN + PT) for submenu and authors page title"}],"acceptanceCriteriaRaw":"- [x] Admin sidebar Articles expands with “All articles” and “Authors”\n- [x] `/admin/articles/authors` is a static route (not `[articleId]`)\n- [x] Authors management page loads without crashing\n- [x] Nav / page i18n (EN + PT) for submenu and authors page title","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-07-29T06:55:45Z","kind":"prompt","author":"Marco Mendão","summary":"Adiciona submenu na sidebar para autores nos artigos; fix crash GET /admin/articles/authors."},{"index":"2","when":"2026-07-29T10:38:42Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work: AC met; session closed."}],"commits":[{"sha":"17934eb","repo":"coachid_app_frontend","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add admin authors page and picture proxy"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T06:55:45Z","ended":"2026-07-29T07:51:29Z","summary":"Authors sidebar submenu + static /admin/articles/authors page; shared-batch: 3344250 of 13377000ms by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-025-author-photo-s3-upload.md":{"id":"T-025","title":"Author photo file upload to S3","type":"task","status":"done","priority":"medium","size":"L","points":5,"estimateMinutes":110,"actualMinutes":111,"actualMs":6688000,"tags":["admin","website","blog","autores","s3"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-009","epic":"E-007","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T07:00:18Z","completedAt":"2026-07-29T10:38:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-025-author-photo-s3-upload.md","description":"Replace the manual author picture URL text field with a file input. Upload images to S3 (same media stack as article covers) and store the public URL / key on the author.","acceptanceCriteria":[{"checked":true,"text":"Admin author create/edit uses a file input (not a URL field)"},{"checked":true,"text":"Selected image is uploaded to S3 under an author-photos prefix"},{"checked":true,"text":"Author list/avatar and article author credit use the stored picture URL"},{"checked":true,"text":"Removing an author (or clearing the photo) deletes the S3 object when managed"},{"checked":true,"text":"Author pictures are served via frontend/API proxy routes (not direct S3 URLs)"}],"acceptanceCriteriaRaw":"- [x] Admin author create/edit uses a file input (not a URL field)\n- [x] Selected image is uploaded to S3 under an author-photos prefix\n- [x] Author list/avatar and article author credit use the stored picture URL\n- [x] Removing an author (or clearing the photo) deletes the S3 object when managed\n- [x] Author pictures are served via frontend/API proxy routes (not direct S3 URLs)","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-07-29T07:00:18Z","kind":"prompt","author":"Marco Mendão","summary":"Foto do autor deve ser file input e guardada no S3."},{"index":"2","when":"2026-07-29T07:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Foto não aparece — servir via rota frontend (não link S3 directo)."},{"index":"3","when":"2026-07-29T07:22:06Z","kind":"prompt","author":"Marco Mendão","summary":"Admins no fim da lista; coluna acções com ⋯ desabilitado para admins (sem —)."},{"index":"4","when":"2026-07-29T10:38:42Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work: AC met; session closed."}],"commits":[{"sha":"6e0eb89","repo":"coachid_app_api","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add article author crud and picture proxy"},{"sha":"17934eb","repo":"coachid_app_frontend","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add admin authors page and picture proxy"},{"sha":"b05ac7b","repo":"coachid-site","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"proxy article author pictures"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T06:55:45Z","ended":"2026-07-29T08:47:13Z","summary":"Author photo file upload to S3 + proxy routes; shared-batch: 6688500 of 13377000ms by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-026-authors-table-ui-search.md":{"id":"T-026","title":"Authors table UI parity + text search","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":55,"actualMinutes":55,"actualMs":3344000,"tags":["admin","website","blog","autores","frontend"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-009","epic":"E-007","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T07:04:46Z","completedAt":"2026-07-29T10:38:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-026-authors-table-ui-search.md","description":"Match the admin authors table UI to the articles table (card layout, search toolbar, bordered table) and add client-side text search.","acceptanceCriteria":[{"checked":true,"text":"Authors page header/actions match articles page shell pattern"},{"checked":true,"text":"Authors table card layout matches articles (search row + bordered table)"},{"checked":true,"text":"Text search filters authors by name, email, or sub"}],"acceptanceCriteriaRaw":"- [x] Authors page header/actions match articles page shell pattern\n- [x] Authors table card layout matches articles (search row + bordered table)\n- [x] Text search filters authors by name, email, or sub","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-07-29T07:04:46Z","kind":"prompt","author":"Marco Mendão","summary":"Tabela de autores similar à de artigos; adicionar pesquisa por texto."},{"index":"2","when":"2026-07-29T10:38:42Z","kind":"feedback","author":"Marco Mendão","summary":"complete-work: AC met; session closed."}],"commits":[{"sha":"17934eb","repo":"coachid_app_frontend","date":"2026-07-29T07:25:44Z","author":"Marco Mendão","message":"add admin authors page and picture proxy"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T06:55:45Z","ended":"2026-07-29T07:51:29Z","summary":"Authors table UI parity + text search; shared-batch: 3344250 of 13377000ms by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-031-editar-descricao-autor-blog.md":{"id":"T-031","title":"Editar descrição do autor do blog (manual e utilizador) e mostrar no site","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["admin","website","blog","autores","description"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-009","epic":"E-007","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-06T13:41:43.000Z","completedAt":"2026-08-10T05:54:44.000Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-031-editar-descricao-autor-blog.md","description":"Nos autores do blog (admin) deve ser possível **editar a descrição** de um autor (ex.: «Marco Mendão, Treinador Profissional da Serie A»). A descrição aplica-se a **autores manuais** e a **autores que são utilizadores do sistema**, e deve ser **mostrada no autor do blog post no site**.","acceptanceCriteria":[{"checked":true,"text":"No admin de autores é possível **editar/guardar** um campo de **descrição** do autor"},{"checked":true,"text":"A descrição é editável para **autores manuais**"},{"checked":true,"text":"A descrição é editável para **autores utilizadores do sistema** (admins / users listados como autores)"},{"checked":true,"text":"A descrição guardada é **exibida** na apresentação do autor do artigo no **site** (coachid-site / página do post)"},{"checked":true,"text":"Descrição vazia tratada de forma limpa (não mostra lixo / placeholder indesejado)"}],"acceptanceCriteriaRaw":"- [x] No admin de autores é possível **editar/guardar** um campo de **descrição** do autor\n- [x] A descrição é editável para **autores manuais**\n- [x] A descrição é editável para **autores utilizadores do sistema** (admins / users listados como autores)\n- [x] A descrição guardada é **exibida** na apresentação do autor do artigo no **site** (coachid-site / página do post)\n- [x] Descrição vazia tratada de forma limpa (não mostra lixo / placeholder indesejado)","reproSteps":"","fixCriteria":"","notes":"Exemplo de conteúdo: nome + cargo/contexto curto. Persistência no modelo de author (API) + UI admin + render no site.","promptFeedback":[{"index":"1","when":"2026-07-30T23:21:22Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — descrição editável nos autores (manuais + users); mostrar no autor do post no site."},{"index":"2","when":"2026-08-06T13:41:43Z","kind":"prompt","author":"Marco Mendão","summary":"implementa isto na worktree-1 T-031"},{"index":"3","when":"2026-08-10T05:54:44Z","kind":"prompt","author":"Marco Mendão","summary":"implementa a tarefa S-009 (fechar T-031 restante)"},{"index":"4","when":"2026-08-10T05:54:44Z","kind":"feedback","author":"Marco Mendão","summary":"T-031 entregue na worktree-1 (API + admin) e coachid-site; AC verificados."}],"commits":[{"sha":"8635482","repo":"coachid_app_api","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"add blog author description api"},{"sha":"476a848","repo":"coachid_app_frontend","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"add author description admin ui"},{"sha":"99a826f","repo":"coachid-site","date":"2026-08-10T06:59:58+01:00","author":"Marco Mendão","message":"show author description on post byline"},{"sha":"47754c4","repo":"coachid-taskmark","date":"2026-07-31T00:21:45+01:00","author":"Marco Mendão","message":"add T-031 blog author description"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-06T13:41:43Z","ended":"2026-08-07T12:00:00Z","summary":"Author description API + admin + site byline; auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md":{"id":"S-010","title":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","type":"story","status":"done","priority":"high","size":"XL","points":20,"estimateMinutes":580,"actualMinutes":572,"actualMs":34321000,"tags":["admin","users","teams","tabs","dashboard"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-007","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T07:54:31Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md","userStory":"Como administrador, quero em `/admin/users` alternar entre a lista de **utilizadores** e a lista de **equipas** via tabs, e na lista de utilizadores ver todos os utilizadores do sistema com datas, total de equipas, contas com acesso e um estado derivado das contas, para gerir e diagnosticar o acesso à plataforma.","acceptanceCriteria":[{"checked":true,"text":"Em `/admin/users` existem tabs que permitem alternar entre **lista de utilizadores** e **lista de equipas**"},{"checked":true,"text":"A tab de utilizadores mostra **todos** os utilizadores do sistema"},{"checked":true,"text":"Cada utilizador tem coluna com o **total de equipas**; ao clicar abre um dialog com tabela de todas as equipas desse utilizador"},{"checked":true,"text":"Cada utilizador tem coluna de **contas com acesso**; ao clicar abre um dialog com lista das contas, estado e informação relevante da subscrição de cada conta"},{"checked":true,"text":"Existem colunas **Criado em** e **Último acesso**"},{"checked":true,"text":"Existe um **estado** do utilizador calculado a partir do estado das suas contas (ex.: activa, trial, etc.)"}],"acceptanceCriteriaRaw":"- [x] Em `/admin/users` existem tabs que permitem alternar entre **lista de utilizadores** e **lista de equipas**\n- [x] A tab de utilizadores mostra **todos** os utilizadores do sistema\n- [x] Cada utilizador tem coluna com o **total de equipas**; ao clicar abre um dialog com tabela de todas as equipas desse utilizador\n- [x] Cada utilizador tem coluna de **contas com acesso**; ao clicar abre um dialog com lista das contas, estado e informação relevante da subscrição de cada conta\n- [x] Existem colunas **Criado em** e **Último acesso**\n- [x] Existe um **estado** do utilizador calculado a partir do estado das suas contas (ex.: activa, trial, etc.)","tasksMarkdown":"- [T-041](items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md) — Lista equipas admin — país sob o nome em vez do desporto\n\n- [T-013](items/T-013-tabs-utilizadores-equipas-admin-users.md) — Tabs Utilizadores / Equipas em /admin/users\n- [T-014](items/T-014-listagem-utilizadores-criado-ultimo-acesso.md) — Listagem de utilizadores com Criado em e Último acesso\n- [T-015](items/T-015-coluna-equipas-dialog.md) — Coluna total de equipas com dialog\n- [T-016](items/T-016-coluna-contas-dialog-subscricao.md) — Coluna contas com acesso e dialog de subscrição\n- [T-017](items/T-017-estado-utilizador-derivado-contas.md) — Estado do utilizador calculado a partir das contas\n- [T-018](items/T-018-accoes-dialogs-equipas-contas.md) — Acções nos dialogs de equipas e contas\n- [T-019](items/T-019-metricas-agregadas-utilizadores.md) — Coluna de métricas agregadas na lista de utilizadores\n- [T-033](items/T-033-modal-subscricao-botao-cliente-stripe.md) — Modal subscrição admin — botão ver cliente no Stripe","children":[{"id":"T-013","title":"Tabs Utilizadores / Equipas em /admin/users","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-013-tabs-utilizadores-equipas-admin-users.md"},{"id":"T-014","title":"Listagem de utilizadores com Criado em e Último acesso","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-014-listagem-utilizadores-criado-ultimo-acesso.md"},{"id":"T-015","title":"Coluna total de equipas com dialog de detalhe","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-015-coluna-equipas-dialog.md"},{"id":"T-016","title":"Coluna contas com acesso e dialog de subscrição","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-016-coluna-contas-dialog-subscricao.md"},{"id":"T-017","title":"Estado do utilizador calculado a partir das contas","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-017-estado-utilizador-derivado-contas.md"},{"id":"T-018","title":"Acções nos dialogs de equipas e contas do utilizador","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-018-accoes-dialogs-equipas-contas.md"},{"id":"T-019","title":"Coluna de métricas agregadas na lista de utilizadores","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-019-metricas-agregadas-utilizadores.md"},{"id":"T-033","title":"Modal subscrição admin — botão ver cliente no Stripe","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-033-modal-subscricao-botao-cliente-stripe.md"},{"id":"T-041","title":"Lista equipas admin — país sob o nome em vez do desporto","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md"}],"promptFeedback":[{"index":"5","when":"2026-07-27T07:42:05Z","kind":"prompt","author":"Marco Mendão","summary":"Coluna métricas no utilizador (soma das equipas) + no dialog de equipas."},{"index":"4","when":"2026-07-27T07:32:49Z","kind":"prompt","author":"Marco Mendão","summary":"Lista de equipas: abrir equipa dentro do menu ⋮."},{"index":"3","when":"2026-07-27T07:30:17Z","kind":"prompt","author":"Marco Mendão","summary":"Dialog equipas: entrar na equipa; dialog contas: acções (desactivar, apagar, dar acesso, etc.)."},{"index":"2","when":"2026-07-27T06:21:00Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 completa."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Admin /admin/users: tabs Utilizadores vs Equipas; lista completa de utilizadores; coluna total equipas + dialog; coluna contas com acesso + dialog de subscrição; colunas Criado em e Último acesso; estado derivado das contas (activa, trial, etc.)."}],"commits":[{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"b4c0c4a","repo":"coachid-taskmark","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"526a73d","repo":"coachid_app_frontend","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"narrow admin users teams and accounts columns"},{"sha":"74615c2","repo":"coachid-taskmark","date":"2026-07-27T08:45:12+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"be8632d","repo":"coachid_app_frontend","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user metrics and dialog actions"},{"sha":"9455f17","repo":"coachid_app_api","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user team metrics"},{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"},{"sha":"d98f5aa","repo":"coachid-taskmark","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add S-010 admin users list story"},{"sha":"e2dca42","repo":"coachid_app_frontend","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"df8f10a","repo":"coachid_app_api","date":"2026-07-27T08:15:09+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T07:18:09Z","summary":"S-010 delivered via shared-batch on T-013..T-017 (billable on leaves)."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-013-tabs-utilizadores-equipas-admin-users.md":{"id":"T-013","title":"Tabs Utilizadores / Equipas em /admin/users","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":9,"actualMs":540000,"tags":["admin","users","teams","tabs","ui"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T06:30:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-013-tabs-utilizadores-equipas-admin-users.md","description":"Na página `/admin/users`, separar a lista de utilizadores da lista de equipas com um controlo de tabs. A tab de equipas mantém a listagem de equipas existente; a tab de utilizadores passa a ser o contentor da nova listagem de utilizadores.","acceptanceCriteria":[{"checked":true,"text":"Em `/admin/users` existem tabs **Utilizadores** e **Equipas**"},{"checked":true,"text":"O utilizador consegue alternar entre as duas listas sem sair da página"},{"checked":true,"text":"A tab Equipas continua a mostrar a listagem de equipas (comportamento actual preservado)"},{"checked":true,"text":"A tab Utilizadores mostra (ou prepara o espaço para) a lista de utilizadores"}],"acceptanceCriteriaRaw":"- [x] Em `/admin/users` existem tabs **Utilizadores** e **Equipas**\n- [x] O utilizador consegue alternar entre as duas listas sem sair da página\n- [x] A tab Equipas continua a mostrar a listagem de equipas (comportamento actual preservado)\n- [x] A tab Utilizadores mostra (ou prepara o espaço para) a lista de utilizadores","reproSteps":"","fixCriteria":"","notes":"Hoje a página só renderiza `AdminTeamsTable` após os summary cards; as tabs devem integrar ambas as vistas.","promptFeedback":[{"index":"2","when":"2026-07-27T07:18:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 no worktree-1."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Separar lista de utilizadores da lista de equipas com tabs em /admin/users."}],"commits":[{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T06:30:00Z","summary":"Delivered T-013 as part of S-010. shared-batch: 9 of 57min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-014-listagem-utilizadores-criado-ultimo-acesso.md":{"id":"T-014","title":"Listagem de utilizadores com Criado em e Último acesso","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":14,"actualMs":840000,"tags":["admin","users","table","api"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T06:35:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-014-listagem-utilizadores-criado-ultimo-acesso.md","description":"Na tab Utilizadores de `/admin/users`, apresentar uma lista com **todos** os utilizadores do sistema, incluindo colunas **Criado em** e **Último acesso** (além dos identificadores básicos necessários).","acceptanceCriteria":[{"checked":true,"text":"A tab Utilizadores lista todos os utilizadores do sistema"},{"checked":true,"text":"Existe coluna **Criado em** com a data de criação do utilizador"},{"checked":true,"text":"Existe coluna **Último acesso** com a data/hora do último acesso (ou indicação clara quando inexistente)"},{"checked":true,"text":"Listagem utilizável (paginação ou equivalente se o volume o exigir)"}],"acceptanceCriteriaRaw":"- [x] A tab Utilizadores lista todos os utilizadores do sistema\n- [x] Existe coluna **Criado em** com a data de criação do utilizador\n- [x] Existe coluna **Último acesso** com a data/hora do último acesso (ou indicação clara quando inexistente)\n- [x] Listagem utilizável (paginação ou equivalente se o volume o exigir)","reproSteps":"","fixCriteria":"","notes":"Pode exigir endpoint/admin API para listar utilizadores com estes campos; alinhar com o padrão das equipas (`AdminTeamsTable`).","promptFeedback":[{"index":"2","when":"2026-07-27T07:18:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 no worktree-1."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Lista com todos os utilizadores; colunas Criado em e Último acesso."}],"commits":[{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T06:35:00Z","summary":"Delivered T-014 as part of S-010. shared-batch: 14 of 57min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-015-coluna-equipas-dialog.md":{"id":"T-015","title":"Coluna total de equipas com dialog de detalhe","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":600000,"tags":["admin","users","teams","dialog"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T06:31:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-015-coluna-equipas-dialog.md","description":"Na lista de utilizadores, adicionar uma coluna com o **total de equipas** do utilizador. Ao clicar, abrir um dialog com uma tabela de **todas as equipas** associadas a esse utilizador.","acceptanceCriteria":[{"checked":true,"text":"Coluna com o total de equipas por utilizador"},{"checked":true,"text":"Clique no total (ou na célula) abre um dialog"},{"checked":true,"text":"O dialog apresenta uma tabela com todas as equipas do utilizador"},{"checked":true,"text":"Dialog utilizável com zero equipas (estado vazio claro)"}],"acceptanceCriteriaRaw":"- [x] Coluna com o total de equipas por utilizador\n- [x] Clique no total (ou na célula) abre um dialog\n- [x] O dialog apresenta uma tabela com todas as equipas do utilizador\n- [x] Dialog utilizável com zero equipas (estado vazio claro)","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"2","when":"2026-07-27T07:18:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 no worktree-1."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Coluna total de equipas; on click dialog com tabela de todas as equipas."}],"commits":[{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T06:31:00Z","summary":"Delivered T-015 as part of S-010. shared-batch: 10 of 57min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-016-coluna-contas-dialog-subscricao.md":{"id":"T-016","title":"Coluna contas com acesso e dialog de subscrição","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":14,"actualMs":840000,"tags":["admin","users","accounts","subscription","dialog"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T06:35:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-016-coluna-contas-dialog-subscricao.md","description":"Na lista de utilizadores, adicionar uma coluna que mostre as **contas a que o utilizador tem acesso**. Ao clicar, abrir um dialog com a lista de contas, o **estado** de cada conta e informação relevante da **subscrição** (plano, trial, datas, etc.).","acceptanceCriteria":[{"checked":true,"text":"Coluna que permite perceber a que contas o utilizador tem acesso (contador e/ou resumo)"},{"checked":true,"text":"Clique abre um dialog com a lista de todas as contas do utilizador"},{"checked":true,"text":"Cada conta no dialog mostra o estado e informação relevante da subscrição"},{"checked":true,"text":"Dialog utilizável com zero contas (estado vazio claro)"}],"acceptanceCriteriaRaw":"- [x] Coluna que permite perceber a que contas o utilizador tem acesso (contador e/ou resumo)\n- [x] Clique abre um dialog com a lista de todas as contas do utilizador\n- [x] Cada conta no dialog mostra o estado e informação relevante da subscrição\n- [x] Dialog utilizável com zero contas (estado vazio claro)","reproSteps":"","fixCriteria":"","notes":"Campos exactos de subscrição a alinhar com o modelo de contas existente no admin.","promptFeedback":[{"index":"2","when":"2026-07-27T07:18:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 no worktree-1."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Coluna contas com acesso; dialog com lista de contas, estado e info de subscrição."}],"commits":[{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T06:35:00Z","summary":"Delivered T-016 as part of S-010. shared-batch: 14 of 57min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-017-estado-utilizador-derivado-contas.md":{"id":"T-017","title":"Estado do utilizador calculado a partir das contas","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":600000,"tags":["admin","users","status","subscription"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T06:21:00Z","completedAt":"2026-07-27T06:31:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-017-estado-utilizador-derivado-contas.md","description":"Na lista de utilizadores, exibir um **estado** do utilizador derivado do estado das suas contas (ex.: tem conta activa, em trial, cancelada, etc.), de forma consistente e legível na tabela.","acceptanceCriteria":[{"checked":true,"text":"Existe coluna (ou badge) de **estado** por utilizador"},{"checked":true,"text":"O estado é **calculado** a partir do estado das contas do utilizador (activa, trial, etc.)"},{"checked":true,"text":"A regra de agregação está documentada no código ou notas (prioridade quando há várias contas com estados diferentes)"},{"checked":true,"text":"Estado visível e coerente com a informação do dialog de contas (T-016)"}],"acceptanceCriteriaRaw":"- [x] Existe coluna (ou badge) de **estado** por utilizador\n- [x] O estado é **calculado** a partir do estado das contas do utilizador (activa, trial, etc.)\n- [x] A regra de agregação está documentada no código ou notas (prioridade quando há várias contas com estados diferentes)\n- [x] Estado visível e coerente com a informação do dialog de contas (T-016)","reproSteps":"","fixCriteria":"","notes":"Definir prioridade de agregação (ex.: activa > trial > outros) quando o utilizador tem múltiplas contas.","promptFeedback":[{"index":"2","when":"2026-07-27T07:18:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-010 no worktree-1."},{"index":"1","when":"2026-07-27T06:05:51Z","kind":"prompt","author":"Marco Mendão","summary":"Estado do utilizador calculado via estado das contas (activa, trial, etc.)."}],"commits":[{"sha":"5317684","repo":"coachid_app_frontend","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users tabs and table"},{"sha":"c13fa04","repo":"coachid_app_api","date":"2026-07-27T08:16:00+01:00","author":"Marco Mendão","message":"add admin users list endpoint"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T06:21:00Z","ended":"2026-07-27T06:31:00Z","summary":"Delivered T-017 as part of S-010. shared-batch: 10 of 57min by points"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-018-accoes-dialogs-equipas-contas.md":{"id":"T-018","title":"Acções nos dialogs de equipas e contas do utilizador","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":25,"actualMinutes":21,"actualMs":1313000,"tags":["admin","users","teams","accounts","dialog"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T07:30:17Z","completedAt":"2026-07-27T07:52:10Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-018-accoes-dialogs-equipas-contas.md","description":"No dialog de equipas da lista de utilizadores, permitir **entrar na equipa** como na vista por equipas. No dialog de contas, adicionar acções por conta (ver subscrição, conceder/estender acesso manual, desactivar, apagar, restaurar).","acceptanceCriteria":[{"checked":true,"text":"Dialog de equipas tem coluna/acção para abrir a equipa (mesmo fluxo da vista por equipas)"},{"checked":true,"text":"Equipa eliminada não permite abrir"},{"checked":true,"text":"Dialog de contas expõe menu de acções por workspace/conta"},{"checked":true,"text":"Acções incluem ver subscrição, acesso manual, desactivar, apagar e restaurar quando aplicável"},{"checked":true,"text":"Após uma acção bem-sucedida, a lista/dialog reflecte o estado actualizado"}],"acceptanceCriteriaRaw":"- [x] Dialog de equipas tem coluna/acção para abrir a equipa (mesmo fluxo da vista por equipas)\n- [x] Equipa eliminada não permite abrir\n- [x] Dialog de contas expõe menu de acções por workspace/conta\n- [x] Acções incluem ver subscrição, acesso manual, desactivar, apagar e restaurar quando aplicável\n- [x] Após uma acção bem-sucedida, a lista/dialog reflecte o estado actualizado","reproSteps":"","fixCriteria":"","notes":"Reutiliza `AdminOpenTeamButton` e os dialogs de conta já usados em `admin-teams-table`.","promptFeedback":[{"index":"2","when":"2026-07-27T07:32:49Z","kind":"prompt","author":"Marco Mendão","summary":"Na lista de equipas, botão abrir equipa deve estar dentro do menu de 3 pontinhos."},{"index":"1","when":"2026-07-27T07:30:17Z","kind":"prompt","author":"Marco Mendão","summary":"Na lista de equipa no dialog: opção entrar na equipa. Na lista de contas: coluna/acções (desactivar, apagar, dar acesso, etc.)."}],"commits":[{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"74615c2","repo":"coachid-taskmark","date":"2026-07-27T08:45:12+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"be8632d","repo":"coachid_app_frontend","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user metrics and dialog actions"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T07:30:17Z","ended":"2026-07-27T07:52:10Z","summary":"Dialog actions and open-team-in-menu delivered. acções nos dialogs de equipas e contas."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-019-metricas-agregadas-utilizadores.md":{"id":"T-019","title":"Coluna de métricas agregadas na lista de utilizadores","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":10,"actualMs":605000,"tags":["admin","users","metrics"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T07:42:05Z","completedAt":"2026-07-27T07:52:10Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-019-metricas-agregadas-utilizadores.md","description":"Adicionar coluna de métricas na lista de utilizadores (soma das métricas das equipas do utilizador) e coluna de métricas no dialog de equipas do utilizador.","acceptanceCriteria":[{"checked":true,"text":"Lista de utilizadores tem coluna de métricas com KPIs agregados das equipas"},{"checked":true,"text":"Exercícios (nível org) não são duplicados na agregação do utilizador"},{"checked":true,"text":"Dialog de equipas do utilizador mostra métricas por equipa"},{"checked":true,"text":"UI reutiliza o mesmo grid visual da lista de equipas"}],"acceptanceCriteriaRaw":"- [x] Lista de utilizadores tem coluna de métricas com KPIs agregados das equipas\n- [x] Exercícios (nível org) não são duplicados na agregação do utilizador\n- [x] Dialog de equipas do utilizador mostra métricas por equipa\n- [x] UI reutiliza o mesmo grid visual da lista de equipas","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"2","when":"2026-07-27T07:45:41Z","kind":"prompt","author":"Marco Mendão","summary":"Colunas Equipas e Contas mais estreitas e centradas."},{"index":"1","when":"2026-07-27T07:42:05Z","kind":"prompt","author":"Marco Mendão","summary":"Coluna métricas no utilizador (soma das equipas) + coluna métricas no dialog de equipas."}],"commits":[{"sha":"73beae2","repo":"coachid-taskmark","date":"2026-07-27T08:57:40+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"b4c0c4a","repo":"coachid-taskmark","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"526a73d","repo":"coachid_app_frontend","date":"2026-07-27T08:50:07+01:00","author":"Marco Mendão","message":"narrow admin users teams and accounts columns"},{"sha":"74615c2","repo":"coachid-taskmark","date":"2026-07-27T08:45:12+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"be8632d","repo":"coachid_app_frontend","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user metrics and dialog actions"},{"sha":"9455f17","repo":"coachid_app_api","date":"2026-07-27T08:44:28+01:00","author":"Marco Mendão","message":"add admin user team metrics"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T07:42:05Z","ended":"2026-07-27T07:52:10Z","summary":"Aggregated user metrics and column sizing delivered. métricas agregadas nos utilizadores."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-033-modal-subscricao-botao-cliente-stripe.md":{"id":"T-033","title":"Modal subscrição admin — botão ver cliente no Stripe","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["admin","stripe","subscription","dialog"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T07:04:12Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-033-modal-subscricao-botao-cliente-stripe.md","description":"Na modal **Ver subscrição** do admin dashboard (lista de equipas e de utilizadores/contas), adicionar um botão que abre o **cliente Stripe** no Dashboard quando existe `stripeCustomerId`.","acceptanceCriteria":[{"checked":true,"text":"Na modal de subscrição, se a conta tem `stripeCustomerId`, aparece um botão para abrir o cliente no Stripe Dashboard (nova tab)"},{"checked":true,"text":"O botão não aparece (ou fica desactivado) quando não há customer Stripe"},{"checked":true,"text":"Funciona na modal da tabela de equipas e na modal de contas do utilizador"},{"checked":true,"text":"i18n EN/PT"}],"acceptanceCriteriaRaw":"- [x] Na modal de subscrição, se a conta tem `stripeCustomerId`, aparece um botão para abrir o cliente no Stripe Dashboard (nova tab)\n- [x] O botão não aparece (ou fica desactivado) quando não há customer Stripe\n- [x] Funciona na modal da tabela de equipas e na modal de contas do utilizador\n- [x] i18n EN/PT","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T07:04:12Z","kind":"prompt","author":"Marco Mendão","summary":"Na modal de ver subscrição no admin deve existir botão para ver o cliente no Stripe."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T07:04:12Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: add Stripe customer link on admin subscription modal. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md":{"id":"T-041","title":"Lista equipas admin — país sob o nome em vez do desporto","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":3,"actualMs":183000,"tags":["admin","teams","ui","copy"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-010","epic":"E-007","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:52:42Z","completedAt":"2026-07-31T16:55:45Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md","description":"Na lista de equipas em administração, sob o nome da equipa aparece o `sportsType` (ex.: football). Deve aparecer o **país** da equipa.","acceptanceCriteria":[{"checked":true,"text":"Sob o nome da equipa na tabela/cards de equipas admin mostra-se o país (não o desporto)"},{"checked":true,"text":"Sem país, a linha secundária fica vazia / omitida"}],"acceptanceCriteriaRaw":"- [x] Sob o nome da equipa na tabela/cards de equipas admin mostra-se o país (não o desporto)\n- [x] Sem país, a linha secundária fica vazia / omitida","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-07-31T16:52:42Z","kind":"prompt","author":"Marco Mendão","summary":"Lista equipas admin: país sob o nome em vez de football."}],"commits":[{"sha":"22b8fa1","repo":"coachid_app_api","date":"2026-07-31T16:53:56Z","author":"Marco Mendão","message":"expose team country on admin teams list"},{"sha":"6a56478","repo":"coachid_app_frontend","date":"2026-07-31T16:53:56Z","author":"Marco Mendão","message":"show country under team name in admin list"},{"sha":"c450a37","repo":"coachid-taskmark","date":"2026-07-31T17:55:54+01:00","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:52:42Z","ended":"2026-07-31T16:55:45Z","summary":"API+FE: country under team name in admin teams list (not sportsType)."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/epic.md":{"id":"E-008","title":"Perfil de Utilizadores e Equipas","type":"epic","status":"done","priority":"medium","size":"—","points":4,"estimateMinutes":75,"actualMinutes":61,"actualMs":3667000,"tags":["module","perfil","utilizadores","equipas"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:43:22Z","completedAt":"2026-08-03T15:57:46Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/epic.md","goal":"Entregar e evoluir o perfil de utilizadores e equipas no CoachID — dados de perfil, avatar, preferências e gestão associada a equipas.","scope":"- Perfil de utilizador e superfícies de equipa\n- Integração com Auth0 e armazenamento de ficheiros quando necessário","outOfScope":"- Módulos de produto (Motor de exercícios, PSE, Wellness, Planeamento, Lineup), Website e Admin dashboard — epics próprios","successMetrics":"- Fluxos principais de perfil e equipas utilizáveis em produção\n- Stories com AC cumpridos","storiesMarkdown":"","children":[{"id":"B-003","title":"Avatar no perfil não sincroniza no Auth0 (usar proxy frontend em vez de S3)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md"},{"id":"B-025","title":"Utilizadores duplicados na lista admin (mesmo auth0Sub)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md"}],"commits":[{"sha":"8b59960","repo":"coachid_app_api","date":"2026-08-03T16:36:46+01:00","author":"Marco Mendão","message":"fix duplicate users same auth0Sub"},{"sha":"1fa3dbf","repo":"coachid_app_frontend","date":"2026-08-03T16:36:46+01:00","author":"Marco Mendão","message":"fix profile completion name check"},{"sha":"ba76147","repo":"coachid-taskmark","date":"2026-07-23T07:25:56+01:00","author":"Marco Mendão","message":"update taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T16:54:10Z","ended":"2026-07-29T16:54:10Z","summary":"rollup: all children done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md":{"id":"B-003","title":"Avatar no perfil não sincroniza no Auth0 (usar proxy frontend em vez de S3)","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":1,"actualMs":70000,"tags":["perfil","avatar","auth0","s3","proxy","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-008","epic":"E-008","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-28T07:43:22Z","completedAt":"2026-07-28T07:44:32Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md","description":"No perfil do utilizador, ao mudar o avatar a alteração é gravada com sucesso na plataforma, mas no Auth0 o utilizador continua sem avatar. A imagem fica com um URL directo S3 (ex.: `https://coachid-files.s3.eu-west-1.amazonaws.com/user-avatars/...`), que não deve ser enviado ao Auth0. Em vez disso, deve existir um **endpoint proxy no frontend** que sirva o ficheiro; **esse URL do proxy** é que deve constar no Auth0.","acceptanceCriteria":[{"checked":true,"text":"Existe um endpoint proxy no frontend que serve o ficheiro de avatar (em vez de expor o URL S3 raw ao Auth0)"},{"checked":true,"text":"Ao actualizar o avatar, o campo `picture` (ou equivalente) no Auth0 usa o URL do **proxy**, não o link S3 directo"},{"checked":true,"text":"Após mudar o avatar na plataforma, o Auth0 reflecte o novo avatar"},{"checked":true,"text":"O avatar continua a funcionar correctamente na UI da plataforma"},{"checked":true,"text":"Links S3 directos deixam de ser enviados ao Auth0 para avatars"}],"acceptanceCriteriaRaw":"- [x] Existe um endpoint proxy no frontend que serve o ficheiro de avatar (em vez de expor o URL S3 raw ao Auth0)\n- [x] Ao actualizar o avatar, o campo `picture` (ou equivalente) no Auth0 usa o URL do **proxy**, não o link S3 directo\n- [x] Após mudar o avatar na plataforma, o Auth0 reflecte o novo avatar\n- [x] O avatar continua a funcionar correctamente na UI da plataforma\n- [x] Links S3 directos deixam de ser enviados ao Auth0 para avatars","reproSteps":"1. Abrir o perfil do utilizador\n2. Alterar/carregar um novo avatar\n3. Confirmar que o avatar aparece correctamente na plataforma CoachID\n4. Verificar o perfil do utilizador no Auth0 — avatar em falta / picture incorrecto\n5. Inspeccionar o valor guardado: URL S3 directo em vez de URL do proxy frontend","fixCriteria":"- [x] Existe um endpoint proxy no frontend que serve o ficheiro de avatar (em vez de expor o URL S3 raw ao Auth0)\n- [x] Ao actualizar o avatar, o campo `picture` (ou equivalente) no Auth0 usa o URL do **proxy**, não o link S3 directo\n- [x] Após mudar o avatar na plataforma, o Auth0 reflecte o novo avatar\n- [x] O avatar continua a funcionar correctamente na UI da plataforma\n- [x] Links S3 directos deixam de ser enviados ao Auth0 para avatars","notes":"General task/bug no epic E-008. Exemplo de URL problemático: `https://coachid-files.s3.eu-west-1.amazonaws.com/user-avatars/auth0|…/….png`","promptFeedback":[{"index":"3","when":"2026-07-28T07:44:32Z","kind":"feedback","author":"Marco Mendão","summary":"B-003 fixed: Auth0 gets proxy URL not S3."},{"index":"2","when":"2026-07-28T07:43:22Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-003: Auth0 picture via proxy frontend."},{"index":"1","when":"2026-07-23T06:17:23Z","kind":"prompt","author":"Marco Mendão","summary":"Avatar muda na plataforma mas Auth0 fica sem picture; S3 URL directo — precisa proxy frontend e esse URL no Auth0."}],"commits":[{"sha":"f888f92","repo":"coachid_app_api","date":"2026-07-28T07:44:31Z","author":"Marco Mendão","message":"send auth0 avatar via frontend proxy url"},{"sha":"ac241c2","repo":"coachid_app_frontend","date":"2026-07-28T07:44:31Z","author":"Marco Mendão","message":"bypass auth middleware for user avatar proxy"},{"sha":"------","repo":"------------","date":"--------","author":"---------","message":""}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-28T07:43:22Z","ended":"2026-07-28T07:44:32Z","summary":"Auth0 picture uses frontend avatar proxy; middleware bypass."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md":{"id":"B-025","title":"Utilizadores duplicados na lista admin (mesmo auth0Sub)","type":"bug","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":60,"actualMinutes":59,"actualMs":3597000,"tags":["perfil","admin","utilizadores","auth0","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-008","epic":"E-008","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T14:57:17Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md","description":"Na tabela admin de utilizadores aparecem linhas duplicadas para a mesma conta (mesmo email, mesmas métricas). Um registo pode ter nome preenchido e último acesso recente; o outro fica sem nome / com acesso mais antigo. Coincide com a introdução do perfil (nome + foto) e do `ProfileCompletionGate`, que dispara `POST /users/me` em paralelo com os layouts.\n\nCausa: `upsertUser` faz find → create sem atomicidade; `auth0Sub` tem índice sparse **não único**. Pedidos concorrentes criam dois documentos com o mesmo `auth0Sub` (~10–20 ms de diferença). Actualizar o perfil (`findOneAndUpdate`) só toca num deles, tornando o duplicado óbvio.","acceptanceCriteria":[{"checked":true,"text":"`upsertUser` é seguro sob concorrência (upsert atómico + tratamento de E11000)"},{"checked":true,"text":"Índice `auth0Sub` único (sparse); migração deduplica docs existentes antes de criar o índice"},{"checked":true,"text":"`uploadUserAvatar` não faz `upsert` que possa criar um segundo User"},{"checked":true,"text":"Lista admin deixa de mostrar o mesmo utilizador em duplicado após migração/fix"}],"acceptanceCriteriaRaw":"- [x] `upsertUser` é seguro sob concorrência (upsert atómico + tratamento de E11000)\n- [x] Índice `auth0Sub` único (sparse); migração deduplica docs existentes antes de criar o índice\n- [x] `uploadUserAvatar` não faz `upsert` que possa criar um segundo User\n- [x] Lista admin deixa de mostrar o mesmo utilizador em duplicado após migração/fix","reproSteps":"1. Utilizador novo (ou limpar docs Mongo do `auth0Sub`) faz login — layouts + ProfileCompletionGate chamam `registerMe` em paralelo\n2. Completar perfil (nome e/ou foto)\n3. Abrir `/admin/users` — duas linhas com o mesmo email e métricas idênticas","fixCriteria":"- [x] `upsertUser` é seguro sob concorrência (upsert atómico + tratamento de E11000)\n- [x] Índice `auth0Sub` único (sparse); migração deduplica docs existentes antes de criar o índice\n- [x] `uploadUserAvatar` não faz `upsert` que possa criar um segundo User\n- [x] Lista admin deixa de mostrar o mesmo utilizador em duplicado após migração/fix","notes":"Worktree: `worktree-1`. Evidência em DEV: pares com `_created` a ~12 ms e mesmo `auth0Sub` (ex. `auth0|6a6cc60c…`, `google-oauth2|114884…`).","promptFeedback":[{"index":"1","when":"2026-08-03T14:57:17Z","kind":"prompt","author":"Marco Mendão","summary":"Utilizadores duplicados na lista admin após perfil (nome/foto); investigar e corrigir na worktree-1."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"8b59960","repo":"coachid_app_api","date":"2026-08-03T16:36:46+01:00","author":"Marco Mendão","message":"fix duplicate users same auth0Sub"},{"sha":"1fa3dbf","repo":"coachid_app_frontend","date":"2026-08-03T16:36:46+01:00","author":"Marco Mendão","message":"fix profile completion name check"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T14:57:17Z","ended":"2026-08-03T15:57:14Z","summary":"In progress: fix upsertUser race + unique auth0Sub + dedupe — completed: AC done; close stale in_progress session"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/epic.md":{"id":"E-009","title":"General","type":"epic","status":"in_progress","priority":"medium","size":"—","points":52,"estimateMinutes":4105,"actualMinutes":2911,"actualMs":174681000,"tags":["general"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T10:03:25Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/epic.md","goal":"Default home for general tasks and user stories that do not have a clearer epic.","scope":"- General user stories created without an explicit epic.\n- General tasks/bugs without an explicit story (`items/` under this epic).","outOfScope":"- Product initiatives that deserve their own epic (move them out of General when known).","successMetrics":"- General tasks and user stories remain visible in the epic list under General.","storiesMarkdown":"- [S-017](stories/S-017-organizacoes-proprias-sem-auth0/story.md) — Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","children":[{"id":"S-017","title":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","type":"story","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md"},{"id":"B-006","title":"Fotos dos jogadores não aparecem no PSE e Wellness (proxy frontend em vez de S3)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md"},{"id":"B-008","title":"Equipas duplicadas no setup/onboarding — retry e guard do wizard","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md"},{"id":"B-014","title":"Frontend build falha (zodResolver SeasonSettings) e avisos ESLint","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md"},{"id":"B-020","title":"Picker de países — lista filtrada ao reabrir e bandeiras","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md"},{"id":"B-021","title":"Picker de países no modal de facturação — clique não selecciona","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md"},{"id":"B-028","title":"Setup/wizard — país não pré-preenche ao escolher equipa do datacenter","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md"},{"id":"B-030","title":"Modal Completa o teu perfil aparece no setup/onboarding wizard","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md"},{"id":"T-010","title":"Ícones PSE e Wellness na sidebar e no sumário da sessão","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md"},{"id":"T-011","title":"Ordenação SMTP — timestamp, prioridade lifecycle, depois reiceivedAt","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md"},{"id":"T-012","title":"Timeline de envio — evento quando PSE/Wellness é respondido ou modificado","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md"},{"id":"T-055","title":"Open Graph — usar og.png como imagem Facebook no site e na app","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md"},{"id":"T-056","title":"Google Analytics — gtag na app e no site","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md"},{"id":"T-066","title":"Script CLI para copiar equipa entre organizações","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md"}],"commits":[{"sha":"------","repo":"------------","date":"--------","author":"---------","message":""},{"sha":"47ab9ce","repo":"coachid-taskmark","date":"2026-07-31T16:51:38Z","author":"Marco Mendão","message":"update country picker and billing board"},{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"},{"sha":"ff7c172","repo":"coachid-taskmark","date":"2026-07-31T16:32:30Z","author":"Marco Mendão","message":"add B-020 country picker bug"},{"sha":"c22c901","repo":"coachid_app_frontend","date":"2026-07-29T16:53:50Z","author":"Marco Mendão","message":"fix season settings build and eslint warnings"},{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"},{"sha":"0b56ff6","repo":"coachid-taskmark","date":"2026-08-10T17:44:58+01:00","author":"Marco Mendão","message":"update taskmark board for S-017"},{"sha":"665ca7b","repo":"coachid_app_api","date":"2026-08-11T01:02:17+01:00","author":"Marco Mendão","message":"add auth0 management 429 retry backoff"},{"sha":"d8d48d0","repo":"coachid-taskmark","date":"2026-08-11T01:02:18+01:00","author":"Marco Mendão","message":"update taskmark board for auth0 retry"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T16:54:10Z","ended":"2026-07-29T16:54:10Z","summary":"rollup: all children done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md":{"id":"B-006","title":"Fotos dos jogadores não aparecem no PSE e Wellness (proxy frontend em vez de S3)","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":2,"actualMs":131000,"tags":["pse","wellness","avatar","jogadores","s3","proxy","bug"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T15:34:49Z","completedAt":"2026-07-23T15:39:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md","description":"No **PSE** (bem-estar / esforço) e no **Wellness**, as fotos dos jogadores não estão a ser mostradas. A causa provável é o uso de um **link directo S3** para o avatar do jogador, que o browser/UI não consegue servir correctamente (CORS, bucket privado, ou URL inválido na UI).\n\nDeve existir um **proxy no frontend** que sirva os avatares dos jogadores; as listagens/detalhes de PSE e Wellness devem usar esse URL do proxy, não o link S3 raw.\n\nRelacionado: [B-003](../../E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md) (proxy de avatar de perfil / Auth0) — reutilizar o mesmo padrão/endpoint se fizer sentido.","acceptanceCriteria":[{"checked":true,"text":"Existe um endpoint proxy no frontend que serve avatares de jogadores (sem expor o URL S3 raw na UI)"},{"checked":true,"text":"Em PSE, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente"},{"checked":true,"text":"Em Wellness, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente"},{"checked":true,"text":"Jogadores sem foto continuam com o fallback/placeholder esperado"},{"checked":true,"text":"Links S3 directos deixam de ser usados como `src` de avatar nas listagens PSE/Wellness"}],"acceptanceCriteriaRaw":"- [x] Existe um endpoint proxy no frontend que serve avatares de jogadores (sem expor o URL S3 raw na UI)\n- [x] Em PSE, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente\n- [x] Em Wellness, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente\n- [x] Jogadores sem foto continuam com o fallback/placeholder esperado\n- [x] Links S3 directos deixam de ser usados como `src` de avatar nas listagens PSE/Wellness","reproSteps":"1. Abrir o módulo PSE com jogadores que têm foto de perfil\n2. Observar que a foto do jogador não é mostrada (placeholder / broken image)\n3. Abrir o módulo Wellness com os mesmos jogadores\n4. Confirmar o mesmo problema nas fotos\n5. Inspeccionar o `src` da imagem: URL S3 directo em vez de URL do proxy frontend","fixCriteria":"- [x] Existe um endpoint proxy no frontend que serve avatares de jogadores (sem expor o URL S3 raw na UI)\n- [x] Em PSE, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente\n- [x] Em Wellness, as fotos dos jogadores usam o URL do **proxy** e são mostradas correctamente\n- [x] Jogadores sem foto continuam com o fallback/placeholder esperado\n- [x] Links S3 directos deixam de ser usados como `src` de avatar nas listagens PSE/Wellness","notes":"Bug transversal PSE + Wellness → epic General (E-009). Severidade alta. Preferir alinhar com o proxy de B-003 se já existir ou for criado em paralelo.","promptFeedback":[{"index":"1","when":"2026-07-23T08:02:31Z","kind":"prompt","author":"Marco Mendão","summary":"Bug no bem-estar e Wellness: fotos dos jogadores não aparecem; URL deve ser proxy frontend (não S3 directo); severidade alta."},{"index":"2","when":"2026-07-23T15:34:49Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-006, T-010 e T-012 (shared-batch)."},{"index":"3","when":"2026-07-23T15:39:54Z","kind":"feedback","author":"Marco Mendão","summary":"Done: toDisplayPhotoUrl em RpesTable/WellnessTable/EditWellnessForm."}],"commits":[{"sha":"9aabdb4","repo":"coachid_app_frontend","date":"2026-07-23T16:40:20+01:00","author":"Marco Mendão","message":"fix player photo proxy icons and response timeline events"},{"sha":"7dadb0d","repo":"coachid-taskmark","date":"2026-07-23T16:40:30+01:00","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T15:34:49Z","ended":"2026-07-23T15:37:00Z","summary":"shared-batch: 131 of 305s by points — player photo proxy PSE/Wellness"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md":{"id":"B-008","title":"Equipas duplicadas no setup/onboarding — retry e guard do wizard","type":"bug","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":4,"actualMs":241000,"tags":["setup","onboarding","teams","concurrency","wizard"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-27","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-27T05:38:29Z","completedAt":"2026-07-27T05:42:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md","description":"Alguns clientes acabam com **equipas iguais criadas em sequência** no setup/onboarding da conta. A investigação aponta para o `CompleteWizard` na página summary: a equipa é persistida primeiro (`PUT /teams`); se season/import falha (ou o user sai e volta), o guard local (`useRef`) é limpo e o summary corre outra vez → **nova equipa com o mesmo nome**.\n\nNão há índice único `(organization, name)` na API; o create não é idempotente.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"Hipóteses relacionadas (fora do scope mínimo destes 3 passos, mas úteis depois): índice único parcial `(organization, name)` na API; `Idempotency-Key` / find-or-create.","promptFeedback":[{"index":"1","when":"2026-07-27T05:33:01Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa/bug: equipas duplicadas no setup; passos — retomar teamId no erro, guard em provider/sessionStorage, desactivar Continuar/Cancel durante create."},{"index":"2","when":"2026-07-27T05:38:29Z","kind":"prompt","author":"Marco Mendão","summary":"Começar a trabalhar no B-008: retomar teamId, guard provider/sessionStorage, disable Continuar/Cancel."},{"index":"3","when":"2026-07-27T05:42:30Z","kind":"feedback","author":"Marco Mendão","summary":"Fix delivered: CompleteWizard resume + sessionStorage/provider guard + disable Continue/Cancel on onboarding and setup."}],"commits":[{"sha":"a592cf9","repo":"coachid-taskmark","date":"2026-07-27T06:33:28Z","author":"Marco Mendão","message":"add B-008 duplicate teams setup wizard bug"},{"sha":"3d73e73","repo":"coachid_app_frontend","date":"2026-07-27T05:42:43Z","author":"Marco Mendão","message":"fix duplicate teams on wizard retry"},{"sha":"1ed3675","repo":"coachid-taskmark","date":"2026-07-27T05:43:29Z","author":"Marco Mendão","message":"complete B-008 duplicate teams wizard fix"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-27T05:38:29Z","ended":"2026-07-27T05:42:30Z","summary":"CompleteWizard resumes teamId/seasonId; sessionStorage + provider guard; disable lineup Continue/Cancel"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md":{"id":"B-014","title":"Frontend build falha (zodResolver SeasonSettings) e avisos ESLint","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":181000,"tags":["frontend","build","eslint","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-29","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-29T16:51:41Z","completedAt":"2026-07-29T16:54:42Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md","description":"`yarn build` em `coachid_app_frontend` falha com erro de tipo em `SeasonSettingsForm` (`z.coerce.number` + `zodResolver`) e emite vários avisos ESLint (`no-unused-vars`, `react-hooks/exhaustive-deps`).","acceptanceCriteria":[{"checked":true,"text":"`yarn build` completa sem erro de tipo"},{"checked":true,"text":"Avisos ESLint reportados no build anterior estão resolvidos (unused vars / hooks deps)"},{"checked":true,"text":"Form de season settings continua a validar meso/micro cycle durations correctamente"}],"acceptanceCriteriaRaw":"- [x] `yarn build` completa sem erro de tipo\n- [x] Avisos ESLint reportados no build anterior estão resolvidos (unused vars / hooks deps)\n- [x] Form de season settings continua a validar meso/micro cycle durations correctamente","reproSteps":"1. Em `coachid_app_frontend`, correr `yarn build` (ou `b`).\n2. Observar falha de compilação em `SeasonSettingsForm.tsx` no `zodResolver(schema)`.\n3. Observar avisos ESLint listados no output do build.","fixCriteria":"- [x] `yarn build` completa sem erro de tipo\n- [x] Avisos ESLint reportados no build anterior estão resolvidos (unused vars / hooks deps)\n- [x] Form de season settings continua a validar meso/micro cycle durations correctamente","notes":"Padrão existente no repo: `zodResolver(schema) as Resolver<FormValues>` (ex. AddWellnessReminderForm).","promptFeedback":[{"index":"1","when":"2026-07-29T16:51:41Z","kind":"prompt","author":"Marco Mendão","summary":"fix build problems and warning; depois commit-all e complete-work a verificar tarefas concluídas."},{"index":"2","when":"2026-07-29T16:54:42Z","kind":"feedback","author":"Marco Mendão","summary":"Build limpo; zodResolver cast + limpeza ESLint; commit c22c901."}],"commits":[{"sha":"c22c901","repo":"coachid_app_frontend","date":"2026-07-29T16:53:50Z","author":"Marco Mendão","message":"fix season settings build and eslint warnings"},{"sha":"6e77a6f","repo":"coachid-taskmark","date":"2026-07-29T16:54:42Z","author":"Marco Mendão","message":"complete B-014 and cascade finished epics"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-29T16:51:41Z","ended":"2026-07-29T16:54:42Z","summary":"Fixed SeasonSettings zodResolver type error and cleared ESLint unused-vars / hooks warnings; yarn build passes."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md":{"id":"B-020","title":"Picker de países — lista filtrada ao reabrir e bandeiras","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["ui","forms","countries","combobox","setup","onboarding","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:33:39Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md","description":"O picker de países (ex.: wizard de adicionar equipa) mostra bandeiras e, ao reabrir após uma selecção, a lista fica filtrada só ao país seleccionado (ex.: só Portugal), em vez da lista completa com o país seleccionado marcado.","acceptanceCriteria":[{"checked":true,"text":"O picker de países **não mostra bandeiras**"},{"checked":true,"text":"Ao abrir o picker com um país já seleccionado, a lista completa aparece com esse país seleccionado (sem filtrar só a esse valor)"},{"checked":true,"text":"A filtragem autocomplete só ocorre quando o utilizador **altera** o texto da combobox"},{"checked":true,"text":"Implementação com o Combobox shadcn ([docs](https://ui.shadcn.com/docs/components/base/combobox)), substituindo/ajustando `CountrySelect` / `CountrySelect2` nos sítios relevantes (setup/onboarding, settings, facturação, etc.)"}],"acceptanceCriteriaRaw":"- [x] O picker de países **não mostra bandeiras**\n- [x] Ao abrir o picker com um país já seleccionado, a lista completa aparece com esse país seleccionado (sem filtrar só a esse valor)\n- [x] A filtragem autocomplete só ocorre quando o utilizador **altera** o texto da combobox\n- [x] Implementação com o Combobox shadcn ([docs](https://ui.shadcn.com/docs/components/base/combobox)), substituindo/ajustando `CountrySelect` / `CountrySelect2` nos sítios relevantes (setup/onboarding, settings, facturação, etc.)","reproSteps":"1. Ir ao wizard de adicionar equipa onde existe o campo **país**.\n2. Seleccionar um país (ex.: Portugal).\n3. Clicar fora do picker; depois clicar no picker outra vez.\n4. Clicar outra vez no picker.","fixCriteria":"- [x] O picker de países **não mostra bandeiras**\n- [x] Ao abrir o picker com um país já seleccionado, a lista completa aparece com esse país seleccionado (sem filtrar só a esse valor)\n- [x] A filtragem autocomplete só ocorre quando o utilizador **altera** o texto da combobox\n- [x] Implementação com o Combobox shadcn ([docs](https://ui.shadcn.com/docs/components/base/combobox)), substituindo/ajustando `CountrySelect` / `CountrySelect2` nos sítios relevantes (setup/onboarding, settings, facturação, etc.)","notes":"Worktree: `worktree-1/coachid_app_frontend`. Componentes actuais: `CountrySelect.tsx`, `CountrySelect2.tsx`.","promptFeedback":[{"index":"2","when":"2026-07-31T16:33:39Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — Resolve o bug B-020 (picker países)."},{"index":"1","when":"2026-07-31T16:32:01Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — bug picker países: sem bandeiras; ao reabrir mostrar lista completa; filtrar só ao editar o texto; usar Combobox shadcn."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"47ab9ce","repo":"coachid-taskmark","date":"2026-07-31T16:51:38Z","author":"Marco Mendão","message":"update country picker and billing board"},{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"},{"sha":"ff7c172","repo":"coachid-taskmark","date":"2026-07-31T16:32:30Z","author":"Marco Mendão","message":"add B-020 country picker bug"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:33:39Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: fix country picker filter and remove flags. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md":{"id":"B-021","title":"Picker de países no modal de facturação — clique não selecciona","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["ui","forms","countries","combobox","dialog","billing","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:40:44Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md","description":"No modal **Dados de faturação** (pré-checkout na página de facturação), a combobox de país abre mas o clique num país não selecciona. No wizard de criação de equipa funciona. Provável conflito de portal/z-index/`pointer-events` com o Dialog Radix.","acceptanceCriteria":[{"checked":true,"text":"É possível seleccionar um país na combobox dentro do modal de facturação"},{"checked":true,"text":"O picker continua a funcionar no wizard de criação de equipas"},{"checked":true,"text":"A lista não fica inacessível por `pointer-events`/portal fora do Dialog"}],"acceptanceCriteriaRaw":"- [x] É possível seleccionar um país na combobox dentro do modal de facturação\n- [x] O picker continua a funcionar no wizard de criação de equipas\n- [x] A lista não fica inacessível por `pointer-events`/portal fora do Dialog","reproSteps":"1. Ir à página de facturação.\n2. Clicar para subscrever o produto.\n3. No modal de dados de facturação, abrir a combobox **país**.\n4. Tentar clicar num país da lista.","fixCriteria":"- [x] É possível seleccionar um país na combobox dentro do modal de facturação\n- [x] O picker continua a funcionar no wizard de criação de equipas\n- [x] A lista não fica inacessível por `pointer-events`/portal fora do Dialog","notes":"Worktree: `worktree-1/coachid_app_frontend`. `CountrySelect2` + `ComboboxContent` + Dialog em `PricingLanding`.","promptFeedback":[{"index":"1","when":"2026-07-31T16:40:44Z","kind":"prompt","author":"Marco Mendão","summary":"Bug: não dá para seleccionar país na combobox do modal de facturação (checkout)."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:40:44Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: fix country combobox clicks inside billing dialog. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md":{"id":"B-028","title":"Setup/wizard — país não pré-preenche ao escolher equipa do datacenter","type":"bug","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":123000,"tags":["bug","setup","onboarding","wizard","country-picker","datacenter"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:23:44Z","completedAt":"2026-08-11T16:27:50Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md","description":"No wizard de criação de equipa / setup inicial, ao seleccionar uma equipa do datacenter (ex. Benfica), o campo de país **deveria** ficar pré-preenchido com o país vindo do datacenter (ex. Portugal). Desde a reformulação do input de países, o país deixa de ser seleccionado automaticamente.\n\nO utilizador deve **continuar a poder alterar** o país manualmente; o bug é só a falta do pré-preenchimento a partir dos dados do datacenter.","acceptanceCriteria":[{"checked":true,"text":"Após escolher uma equipa do datacenter, o país aparece **pré-preenchido** com o país fornecido pelo datacenter (ex. Benfica → Portugal)"},{"checked":true,"text":"O utilizador **pode sempre mudar** o país depois do pré-preenchimento"},{"checked":true,"text":"Comportamento correcto no wizard de criação de equipa e no setup inicial"},{"checked":true,"text":"Compatível com o input de países reformulado (mesmo componente/padrão de [B-020](B-020-picker-paises-filtro-bandeiras-combobox.md) / [B-021](B-021-picker-paises-modal-facturacao-clique.md))"}],"acceptanceCriteriaRaw":"- [x] Após escolher uma equipa do datacenter, o país aparece **pré-preenchido** com o país fornecido pelo datacenter (ex. Benfica → Portugal)\n- [x] O utilizador **pode sempre mudar** o país depois do pré-preenchimento\n- [x] Comportamento correcto no wizard de criação de equipa e no setup inicial\n- [x] Compatível com o input de países reformulado (mesmo componente/padrão de [B-020](B-020-picker-paises-filtro-bandeiras-combobox.md) / [B-021](B-021-picker-paises-modal-facturacao-clique.md))","reproSteps":"1. Ir para o wizard de criação de equipa ou de setup inicial\n2. Seleccionar uma equipa do datacenter (exemplo: Benfica)\n3. Observar o campo de país","fixCriteria":"- [x] Após escolher uma equipa do datacenter, o país aparece **pré-preenchido** com o país fornecido pelo datacenter (ex. Benfica → Portugal)\n- [x] O utilizador **pode sempre mudar** o país depois do pré-preenchimento\n- [x] Comportamento correcto no wizard de criação de equipa e no setup inicial\n- [x] Compatível com o input de países reformulado (mesmo componente/padrão de [B-020](B-020-picker-paises-filtro-bandeiras-combobox.md) / [B-021](B-021-picker-paises-modal-facturacao-clique.md))","notes":"- Regressão: API-Football devolve país só com nome (`cca2: \"\"`); `CountrySelect2` pós B-020 exige `cca2`.\n- Fix: `resolveRestCountry` + normalização em `applyPick` (setup/onboarding/settings) + picker resolve name-only.","promptFeedback":[{"index":"1","when":"2026-08-10T06:20:52Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task bug — wizard/setup: ao escolher equipa do datacenter (ex. Benfica) o país não pré-preenche (devia Portugal); desde reformulação do input de países; país deve permanecer editável."},{"index":"2","when":"2026-08-11T16:23:44Z","kind":"prompt","author":"Marco Mendão","summary":"Resolve o bug B-027 e B-028"}],"commits":[{"sha":"3a23b1f","repo":"coachid_app_frontend","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"fix arrow paste curve and datacenter country prefill"},{"sha":"cdb1892","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"fix arrow paste curve and datacenter country prefill"},{"sha":"b724190","repo":"coachid-taskmark","date":"2026-08-11T16:48:24Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:23:44Z","ended":"2026-08-11T16:25:47Z","summary":"shared-batch: 2 of ~4min by points — resolveRestCountry + applyPick + CountrySelect2"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md":{"id":"B-030","title":"Modal Completa o teu perfil aparece no setup/onboarding wizard","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["perfil","setup","onboarding","dialog","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T16:56:55Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md","description":"O modal **Completa o teu perfil** (`ProfileCompletionGate`) aparece por cima do wizard de setup/onboarding inicial. Só deve aparecer depois de o utilizador ter criado pelo menos uma equipa (e fora das rotas de wizard).","acceptanceCriteria":[{"checked":true,"text":"O modal **não** aparece em rotas `/setup/`, `/onboarding/` ou `/create-organization/`"},{"checked":true,"text":"O modal **não** aparece se o workspace não tiver pelo menos uma equipa activa"},{"checked":true,"text":"Com ≥1 equipa e perfil incompleto, o modal continua a aparecer no app (fora do wizard e da página de perfil)"}],"acceptanceCriteriaRaw":"- [x] O modal **não** aparece em rotas `/setup/`, `/onboarding/` ou `/create-organization/`\n- [x] O modal **não** aparece se o workspace não tiver pelo menos uma equipa activa\n- [x] Com ≥1 equipa e perfil incompleto, o modal continua a aparecer no app (fora do wizard e da página de perfil)","reproSteps":"1. Novo utilizador (ou workspace sem equipas) com nome incompleto no Auth0.\n2. Entrar no fluxo `/onboarding` ou `/setup`.\n3. Observar o modal por cima do wizard.","fixCriteria":"- [x] O modal **não** aparece em rotas `/setup/`, `/onboarding/` ou `/create-organization/`\n- [x] O modal **não** aparece se o workspace não tiver pelo menos uma equipa activa\n- [x] Com ≥1 equipa e perfil incompleto, o modal continua a aparecer no app (fora do wizard e da página de perfil)","notes":"Worktree: `worktree-1/coachid_app_frontend`. Espelha o padrão de B-019 (`BillingCompletionGate`).","promptFeedback":[{"index":"1","when":"2026-08-10T16:56:55Z","kind":"prompt","author":"Marco Mendão","summary":"Modal Completa o teu perfil nunca sobre o wizard; só depois de criar equipa."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T16:56:55Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: hide profile completion modal during setup until team exists. · auto-closed: idle cap (next-day 12:00 UTC); profile modal gated until team exists"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md":{"id":"T-010","title":"Ícones PSE e Wellness na sidebar e no sumário da sessão","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":360,"actualMinutes":359,"actualMs":21595000,"tags":["ui","icons","pse","wellness","navigation","planning"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T15:34:49Z","completedAt":"2026-07-23T17:05:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md","description":"Actualizar os ícones de PSE e Wellness (Bem-estar) para os Tabler Icons:\n\n- **PSE:** `IconPlayFootball` (Play-football)\n- **Wellness / Bem-estar:** `IconCheckupList` (check-up list)\n\nAplicar em:\n\n1. **Sidebar** (desktop e mobile) — entradas PSE e Wellness sob a secção Saúde (hoje `IconGauge` / `IconMoodSmile` em `DesktopNav` / `MobileNav`)\n2. **Cartão “Sumário da sessão”** na criação/edição de treino — indicadores PSE e Wellness no overview (`TrainingSessionMetricsPanel` e quaisquer sítios equivalentes no fluxo de jogo, se usarem os mesmos ícones)","acceptanceCriteria":[{"checked":true,"text":"Na sidebar (desktop), o item PSE usa `IconPlayFootball`"},{"checked":true,"text":"Na sidebar (desktop), o item Wellness/Bem-estar usa `IconCheckupList`"},{"checked":true,"text":"Na sidebar (mobile), os mesmos ícones PSE / Wellness"},{"checked":true,"text":"No cartão “Sumário da sessão” (criação/edição de treino), o indicador PSE usa `IconPlayFootball`"},{"checked":true,"text":"No mesmo cartão, o indicador Wellness usa `IconCheckupList`"},{"checked":true,"text":"Sem regressão visual noutros módulos (ícone de secção Saúde / lineup / etc. inalterados salvo se forem o mesmo item)"},{"checked":true,"text":"Em `HealthTabs` (PSE / Wellness), os mesmos ícones da sidebar"}],"acceptanceCriteriaRaw":"- [x] Na sidebar (desktop), o item PSE usa `IconPlayFootball`\n- [x] Na sidebar (desktop), o item Wellness/Bem-estar usa `IconCheckupList`\n- [x] Na sidebar (mobile), os mesmos ícones PSE / Wellness\n- [x] No cartão “Sumário da sessão” (criação/edição de treino), o indicador PSE usa `IconPlayFootball`\n- [x] No mesmo cartão, o indicador Wellness usa `IconCheckupList`\n- [x] Sem regressão visual noutros módulos (ícone de secção Saúde / lineup / etc. inalterados salvo se forem o mesmo item)\n- [x] Em `HealthTabs` (PSE / Wellness), os mesmos ícones da sidebar","reproSteps":"","fixCriteria":"","notes":"Transversal PSE + Wellness + Planeamento → epic **General** (E-009).\n\nFicheiros-chave (app frontend):\n\n- `src/components/layout/AppLayout/DesktopNav.tsx`\n- `src/components/layout/AppLayout/MobileNav.tsx`\n- `src/app/.../calendar/training/add/TrainingSessionMetricsPanel.tsx`\n- `src/components/commons/HealthTabs.tsx`\n\nTabler: `@tabler/icons-react` — `IconPlayFootball`, `IconCheckupList`.","promptFeedback":[{"index":"1","when":"2026-07-23T09:41:25Z","kind":"prompt","author":"Marco Mendão","summary":"Ícones sidebar PSE=Play-football, Bem-estar=check-up list; mesmos ícones no sumário da sessão na criação/edição de treino."},{"index":"2","when":"2026-07-23T15:34:49Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-006, T-010 e T-012."},{"index":"3","when":"2026-07-23T15:39:54Z","kind":"feedback","author":"Marco Mendão","summary":"Ícones PlayFootball / CheckupList na nav e sumário."},{"index":"4","when":"2026-07-23T17:04:35Z","kind":"prompt","author":"Marco Mendão","summary":"HealthTabs PSE/Wellness ainda com Gauge/MoodSmile — alinhar à sidebar."},{"index":"5","when":"2026-07-23T17:05:30Z","kind":"feedback","author":"Marco Mendão","summary":"HealthTabs alinhado a IconPlayFootball / IconCheckupList."}],"commits":[{"sha":"bff0870","repo":"coachid_app_frontend","date":"2026-07-23T18:05:31Z","author":"Marco Mendão","message":"align health and exercise tab icons with sidebar"},{"sha":"9aabdb4","repo":"coachid_app_frontend","date":"2026-07-23T16:40:20+01:00","author":"Marco Mendão","message":"fix player photo proxy icons and response timeline events"},{"sha":"7dadb0d","repo":"coachid-taskmark","date":"2026-07-23T16:40:30+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"0f8d366","repo":"coachid-taskmark","date":"2026-07-23T10:43:10+01:00","author":"Marco Mendão","message":"sync taskmark board"},{"sha":"d8bd4af","repo":"coachid-taskmark","date":"2026-07-23T18:05:31Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T15:34:49Z","ended":"2026-07-23T15:35:32Z","summary":"shared-batch: 43 of 305s by points — IconPlayFootball / CheckupList"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T09:43:10Z","ended":"2026-07-23T15:40:30Z","summary":"auto-recovered: commit span"},{"session":"3","actor":"Marco Mendão","started":"2026-07-23T17:03:00Z","ended":"2026-07-23T17:04:52Z","summary":"shared-batch: 112500 of 150000ms by points — HealthTabs ícones = sidebar"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md":{"id":"T-011","title":"Ordenação SMTP — timestamp, prioridade lifecycle, depois reiceivedAt","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":120,"actualMinutes":2,"actualMs":127000,"tags":["pse","wellness","email","smtp","frontend"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T10:03:25Z","completedAt":"2026-07-23T10:05:32Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md","description":"O badge / estado de envio PSE e Wellness usa `sortEmailEventsAscending` em `emailEventOrder.ts`. Hoje a chave primária é `reiceivedAt` (quando o webhook chegou ao servidor). Isso falha quando SendGrid entrega webhooks fora de ordem: o evento com `timestamp` SG mais antigo pode ter `reiceivedAt` maior e ficar como “estado actual” (ex. **processed** em vez de **delivered**).\n\nExemplo real (Wellness): `delivered` com `timestamp` 1784631602 e `reiceivedAt` 1784631610113 vs `processed` com `timestamp` 1784631601 e `reiceivedAt` 1784631610117 → UI mostra processed.\n\nOrdenação alvo (desempate ideal):\n\n1. **`timestamp`** — ordem real do evento SendGrid (segundos → ms)\n2. **prioridade de lifecycle** — `delivered` > `processed` > `sending` (e restantes já em `emailEventPriority`)\n3. **`reiceivedAt`** (ou índice original) — só se ainda empatar\n\nAplicar a PSE e Wellness (util partilhado). Actualizar testes com o payload invertido e o caso de empate no mesmo segundo.","acceptanceCriteria":[{"checked":true,"text":"`emailEventSortMs` / `sortEmailEventsAscending` ordenam por `timestamp` primeiro (não por `reiceivedAt` como chave primária)"},{"checked":true,"text":"No mesmo `timestamp`, o desempate é `emailEventPriority` (delivered vence processed/sending)"},{"checked":true,"text":"Só após empate de timestamp **e** prioridade se usa `reiceivedAt` (ou índice) como último critério"},{"checked":true,"text":"Teste com o payload real (processed `reiceivedAt` > delivered `reiceivedAt`, timestamps diferentes) → último evento / badge = **delivered**"},{"checked":true,"text":"Teste de empate no mesmo segundo + `reiceivedAt` iguais ou invertidos → **delivered** via prioridade"},{"checked":true,"text":"Badge PSE e Wellness (`getSmtpStatus` / `SmtpStatusBadge`) reflectem a nova ordem sem regressão nos tons existentes"}],"acceptanceCriteriaRaw":"- [x] `emailEventSortMs` / `sortEmailEventsAscending` ordenam por `timestamp` primeiro (não por `reiceivedAt` como chave primária)\n- [x] No mesmo `timestamp`, o desempate é `emailEventPriority` (delivered vence processed/sending)\n- [x] Só após empate de timestamp **e** prioridade se usa `reiceivedAt` (ou índice) como último critério\n- [x] Teste com o payload real (processed `reiceivedAt` > delivered `reiceivedAt`, timestamps diferentes) → último evento / badge = **delivered**\n- [x] Teste de empate no mesmo segundo + `reiceivedAt` iguais ou invertidos → **delivered** via prioridade\n- [x] Badge PSE e Wellness (`getSmtpStatus` / `SmtpStatusBadge`) reflectem a nova ordem sem regressão nos tons existentes","reproSteps":"","fixCriteria":"","notes":"Ficheiros-chave (worktree-1):\n\n- `coachid_app_frontend/src/components/commons/emailEventOrder.ts`\n- `coachid_app_frontend/src/components/commons/emailEventOrder.test.ts`\n- `coachid_app_frontend/src/components/commons/smtpStatus.ts`\n\nRelacionado: B-005 (introduziu prioridade + preferência por `reiceivedAt`), B-007 (spam PSE).\n\nGeneral task no epic E-009 (partilhado PSE + Wellness).","promptFeedback":[{"index":"1","when":"2026-07-23T10:01:21Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa para ordenação SMTP: timestamp → prioridade lifecycle → reiceivedAt."},{"index":"2","when":"2026-07-23T10:03:25Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-011."},{"index":"3","when":"2026-07-23T10:05:32Z","kind":"feedback","author":"Marco Mendão","summary":"Implementado em worktree-1; 5 testes OK (payload invertido + mesmo segundo)."}],"commits":[{"sha":"6dbb272","repo":"coachid_app_frontend","date":"2026-07-23T11:07:24+01:00","author":"Marco Mendão","message":"fix smtp status sort by timestamp then priority"},{"sha":"5b27fbe","repo":"coachid-taskmark","date":"2026-07-23T11:07:24+01:00","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T10:03:25Z","ended":"2026-07-23T10:05:32Z","summary":"Sort: timestamp → priority → reiceivedAt; testes payload real + empate mesmo segundo."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md":{"id":"T-012","title":"Timeline de envio — evento quando PSE/Wellness é respondido ou modificado","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":27,"actualMs":1677000,"tags":["pse","wellness","email","smtp","timeline","audit"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-07-23","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-23T15:34:49Z","completedAt":"2026-07-23T15:39:54Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md","description":"Na timeline de eventos do botão de envio (PSE e Wellness — [S-003](../../E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md) / [S-004](../../E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md)), além dos eventos SMTP (sending / processed / delivered / …), deve registar-se um evento quando o PSE (RPE) ou o Wellness é **respondido** ou **modificado**, com indicação de **quem** o fez:\n\n- **Jogador** — resposta (ou alteração) feita pelo próprio jogador (fluxo público / link do email)\n- **Utilizador da plataforma** — resposta ou edição feita por um coach/staff autenticado na app\n\nO evento deve entrar no mesmo array `events` usado pela timeline/hover, com `timestamp` coerente com a ordenação partilhada ([T-011](T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md)), e aparecer na preview e na tabela “ver mais”.","acceptanceCriteria":[{"checked":true,"text":"Ao submeter uma resposta PSE (jogador), é acrescentado um evento na timeline desse jogador/sessão (ex. `responded` / nome acordado) com actor = jogador"},{"checked":true,"text":"Ao submeter ou editar PSE na plataforma (utilizador autenticado), é acrescentado um evento com actor = utilizador da plataforma (idealmente id/nome do user)"},{"checked":true,"text":"O mesmo para Wellness: resposta do jogador vs edição/resposta na plataforma"},{"checked":true,"text":"A timeline / tabela mostra o tipo de evento e quem respondeu/modificou (i18n pt/en)"},{"checked":true,"text":"Ordenação continua a usar o util partilhado; o novo evento tem prioridade de lifecycle definida (não “roubar” o badge SMTP de delivered/processed de forma incorrecta — ou badge ignora estes eventos de audit)"},{"checked":true,"text":"Cobertura PSE e Wellness (API + UI worktree / frontend partilhado)"}],"acceptanceCriteriaRaw":"- [x] Ao submeter uma resposta PSE (jogador), é acrescentado um evento na timeline desse jogador/sessão (ex. `responded` / nome acordado) com actor = jogador\n- [x] Ao submeter ou editar PSE na plataforma (utilizador autenticado), é acrescentado um evento com actor = utilizador da plataforma (idealmente id/nome do user)\n- [x] O mesmo para Wellness: resposta do jogador vs edição/resposta na plataforma\n- [x] A timeline / tabela mostra o tipo de evento e quem respondeu/modificou (i18n pt/en)\n- [x] Ordenação continua a usar o util partilhado; o novo evento tem prioridade de lifecycle definida (não “roubar” o badge SMTP de delivered/processed de forma incorrecta — ou badge ignora estes eventos de audit)\n- [x] Cobertura PSE e Wellness (API + UI worktree / frontend partilhado)","reproSteps":"","fixCriteria":"","notes":"- UI: `EmailEventsTimelineHover`, botões de envio PSE/Wellness\n- API: pontos de submit/update RPE e Wellness (player link vs app)\n- Decidir nomes de `event` estáveis (`responded`, `updated`, …) e campos (`actorType`: `player` | `user`, `actorId`, `actorName`, …)\n- Relacionado: S-003, S-004, T-011\n\nGeneral task no epic E-009 (partilhado PSE + Wellness).","promptFeedback":[{"index":"1","when":"2026-07-23T15:27:02Z","kind":"prompt","author":"Marco Mendão","summary":"Criar task: na timeline do botão de envio PSE/Wellness registar evento quando respondido/modificado e quem (jogador vs utilizador da plataforma)."},{"index":"2","when":"2026-07-23T15:34:49Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar B-006, T-010 e T-012."},{"index":"3","when":"2026-07-23T15:39:54Z","kind":"feedback","author":"Marco Mendão","summary":"Eventos responded/updated com actor player/user; badge SMTP ignora audit."},{"index":"4","when":"2026-07-23T16:00:00Z","kind":"feedback","author":"Marco Mendão","summary":"Fix: RPE $push + schema events array; Wellness actor fields no DTO (whitelist); EditDialog refresca events."},{"index":"5","when":"2026-07-23T16:09:20Z","kind":"feedback","author":"Marco Mendão","summary":"Absent event + actor por nome jogador; labels Foi respondido/Foi atualizado."}],"commits":[{"sha":"9c790d0","repo":"coachid_app_api","date":"2026-07-23T17:00:35+01:00","author":"Marco Mendão","message":"fix persist response audit events on rpe and wellness save"},{"sha":"c00d00f","repo":"coachid_app_frontend","date":"2026-07-23T17:00:35+01:00","author":"Marco Mendão","message":"refresh rpe events in ui after platform edit"},{"sha":"ab90f22","repo":"coachid_app_api","date":"2026-07-23T16:40:20+01:00","author":"Marco Mendão","message":"add response audit events on pse and wellness updates"},{"sha":"9aabdb4","repo":"coachid_app_frontend","date":"2026-07-23T16:40:20+01:00","author":"Marco Mendão","message":"fix player photo proxy icons and response timeline events"},{"sha":"7dadb0d","repo":"coachid-taskmark","date":"2026-07-23T16:40:30+01:00","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-23T15:34:49Z","ended":"2026-07-23T15:37:00Z","summary":"shared-batch: 131 of 305s by points — responded/updated audit events API+UI"},{"session":"2","actor":"Marco Mendão","started":"2026-07-23T15:34:49Z","ended":"2026-07-23T16:00:35Z","summary":"auto-recovered: commit span"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md":{"id":"T-055","title":"Open Graph — usar og.png como imagem Facebook no site e na app","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"tags":["seo","opengraph","facebook","metadata","website","frontend"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:48:58Z","completedAt":"2026-08-11T16:50:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md","description":"Configurar os metadados **Facebook Open Graph** no **site** (`coachid-site`) e na **aplicação** (`coachid_app_frontend`) para usarem a imagem `coachid_app_frontend/public/og.png` como `og:image` (e equivalentes necessários para partilha no Facebook).","acceptanceCriteria":[{"checked":true,"text":"No **site**, os metadados Open Graph apontam para esta imagem (`og.png`) como `og:image`"},{"checked":true,"text":"Na **aplicação**, os metadados Open Graph apontam para a mesma asset (URL absoluta pública correcta)"},{"checked":true,"text":"Tags relevantes (`og:image`, e se aplicável `og:image:width` / `og:image:height` / `og:type`) estão presentes e coerentes"},{"checked":true,"text":"A imagem é servida publicamente (path estável; copiar/replicar para o site se necessário)"},{"checked":true,"text":"Validável no [Facebook Sharing Debugger](https://developers.facebook.com/tools/debug/) (ou equivalente) sem imagem em falta"}],"acceptanceCriteriaRaw":"- [x] No **site**, os metadados Open Graph apontam para esta imagem (`og.png`) como `og:image`\n- [x] Na **aplicação**, os metadados Open Graph apontam para a mesma asset (URL absoluta pública correcta)\n- [x] Tags relevantes (`og:image`, e se aplicável `og:image:width` / `og:image:height` / `og:type`) estão presentes e coerentes\n- [x] A imagem é servida publicamente (path estável; copiar/replicar para o site se necessário)\n- [x] Validável no [Facebook Sharing Debugger](https://developers.facebook.com/tools/debug/) (ou equivalente) sem imagem em falta","reproSteps":"","fixCriteria":"","notes":"Asset em `public/og.png` (1200×630) no site e na app. App: `metadata.openGraph.images` → `/og.png` + width/height. Site: `buildSiteMetadata` default → `https://coachidapp.com/og.png`. Re-scrape no debugger após deploy (produção ainda pode servir 404/redirect antigo).","promptFeedback":[{"index":"1","when":"2026-08-10T06:53:58Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — site e app: usar og.png como og:image nos metadados Facebook Open Graph."},{"index":"2","when":"2026-08-11T16:48:58Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-055, T-056; verificar se T-057 está terminada"}],"commits":[{"sha":"88720ed","repo":"coachid_app_frontend","date":"2026-08-10T07:23:24Z","author":"Marco Mendão","message":"add og.png"},{"sha":"13e770a","repo":"coachid-site","date":"2026-08-10T07:23:24Z","author":"Marco Mendão","message":"add og.png"},{"sha":"7fe6ac7","repo":"coachid_app_frontend","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"fix og.png metadata and app analytics id"},{"sha":"693561b","repo":"coachid-site","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"use og.png for default open graph image"},{"sha":"0e45c22","repo":"coachid-taskmark","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:48:58Z","ended":"2026-08-11T16:49:55Z","summary":"shared-batch: 1 of ~2min by points — site+app og.png as og:image"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md":{"id":"T-056","title":"Google Analytics — gtag na app e no site","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":0,"actualMs":57000,"tags":["analytics","google-analytics","gtag","website","frontend"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T16:48:58Z","completedAt":"2026-08-11T16:50:53Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md","description":"Adicionar o Google tag (gtag.js) em ambos os frontends Next.js, com measurement IDs distintos:\n\n- **coachid_app_frontend** → `G-TTT5YQLL3B`\n- **coachid-site** → `G-LT01SR5SWG`\n\nPreferir integração via `next/script` (ou equivalente no layout raiz).","acceptanceCriteria":[{"checked":true,"text":"`coachid_app_frontend` carrega gtag com `G-TTT5YQLL3B` no layout raiz (todas as páginas)"},{"checked":true,"text":"`coachid-site` carrega gtag com `G-LT01SR5SWG` no layout raiz (todas as páginas)"},{"checked":true,"text":"Scripts não bloqueiam o render crítico (async / `next/script` strategy adequada)"},{"checked":true,"text":"IDs não estão trocados entre app e site"},{"checked":true,"text":"Em produção, o Network/GA Realtime confirma hits de ambos os origins"}],"acceptanceCriteriaRaw":"- [x] `coachid_app_frontend` carrega gtag com `G-TTT5YQLL3B` no layout raiz (todas as páginas)\n- [x] `coachid-site` carrega gtag com `G-LT01SR5SWG` no layout raiz (todas as páginas)\n- [x] Scripts não bloqueiam o render crítico (async / `next/script` strategy adequada)\n- [x] IDs não estão trocados entre app e site\n- [x] Em produção, o Network/GA Realtime confirma hits de ambos os origins","reproSteps":"","fixCriteria":"","notes":"Site já tinha `G-LT01SR5SWG`. App tinha o ID do site por engano — corrigido para `G-TTT5YQLL3B`. `next/script` + `afterInteractive`. Confirmar Realtime após deploy.","promptFeedback":[{"index":"1","when":"2026-08-10T07:02:24Z","kind":"prompt","author":"Marco Mendão","summary":"create-task: adicionar GA gtag app G-TTT5YQLL3B e site G-LT01SR5SWG"},{"index":"2","when":"2026-08-11T16:48:58Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar T-055, T-056; verificar se T-057 está terminada"}],"commits":[{"sha":"7fe6ac7","repo":"coachid_app_frontend","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"fix og.png metadata and app analytics id"},{"sha":"7c618ae","repo":"coachid_app_frontend (worktree-1)","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"fix app google analytics measurement id"},{"sha":"0e45c22","repo":"coachid-taskmark","date":"2026-08-11T16:52:47Z","author":"Marco Mendão","message":"sync taskmark board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T16:48:58Z","ended":"2026-08-11T16:49:55Z","summary":"shared-batch: 1 of ~2min by points — fix app GA id to G-TTT5YQLL3B"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md":{"id":"T-066","title":"Script CLI para copiar equipa entre organizações","type":"task","status":"done","priority":"high","size":"XS","points":1,"estimateMinutes":40,"actualMinutes":39,"actualMs":2358000,"tags":["ops","mongo","script","team","migration"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T15:28:51Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md","description":"Script interactivo (inquirer) na API que pede a connection string MongoDB, a organização/user de origem e a de destino, e copia uma equipa com **todos** os dados associados: épocas, plantel/jogadores, planeamento (appointments), RPE/PSE, wellness, etc.","acceptanceCriteria":[{"checked":true,"text":"npm script (ex. `copy:team`) corre via ts-node"},{"checked":true,"text":"Pede connection string (ou credenciais) e confirma a base"},{"checked":true,"text":"Pede ID da equipa de origem e ID da conta de destino (sem listas)"},{"checked":true,"text":"Copia equipa + épocas + jogadores do plantel + teamPlayers + appointments (treino/jogo) + RPEs + wellnesses com novos IDs e refs remapeadas"},{"checked":true,"text":"Dry-run por defeito; `--execute` escreve na BD"},{"checked":true,"text":"Não copia subscrições, tickets de suporte nem memberships da org"}],"acceptanceCriteriaRaw":"- [x] npm script (ex. `copy:team`) corre via ts-node\n- [x] Pede connection string (ou credenciais) e confirma a base\n- [x] Pede ID da equipa de origem e ID da conta de destino (sem listas)\n- [x] Copia equipa + épocas + jogadores do plantel + teamPlayers + appointments (treino/jogo) + RPEs + wellnesses com novos IDs e refs remapeadas\n- [x] Dry-run por defeito; `--execute` escreve na BD\n- [x] Não copia subscrições, tickets de suporte nem memberships da org","reproSteps":"","fixCriteria":"","notes":"Nome do script: `src/scripts/copy-team.ts` · npm: `copy:team`\n\n```bash\nnpm run copy:team # dry-run\nnpm run copy:team -- --execute # escreve (pede confirmação do org destino)\nnpm run copy:team -- --execute --no-copy-exercises\n```\n\nCopia: teams, seasons, players (plantel), teamPlayers, appointments, rpes, wellnesses; opcionalmente exercises referenciados nos treinos. Media S3 fica com os URLs originais (não re-upload).","promptFeedback":[{"index":"1","when":"2026-08-11T15:28:51Z","kind":"prompt","author":"Marco Mendão","summary":"Criar script CLI copy team entre orgs (connection string, origem/destino, dados completos) e começar a implementar"},{"index":"2","when":"2026-08-11T15:37:08Z","kind":"prompt","author":"Marco Mendão","summary":"UX: em vez de listas, pedir ID da equipa e ID da conta destino"}],"commits":[{"sha":"3cfee23","repo":"coachid_app_api","date":"2026-08-11T16:17:07Z","author":"Marco Mendão","message":"document copy-team npm script in env example"},{"sha":"e60f678","repo":"coachid_app_api","date":"2026-08-11T16:16:38Z","author":"Marco Mendão","message":"add copy-team cli script"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T15:28:51Z","ended":"2026-08-11T16:08:09Z","summary":"In progress: implement copy-team CLI script · copy-team CLI: prompts team id + dest account; dry-run/--execute"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md":{"id":"S-017","title":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","type":"story","status":"done","priority":"critical","size":"XL","points":24,"estimateMinutes":1390,"actualMinutes":1028,"actualMs":61734000,"tags":["organizacoes","auth0","migracao","setup-wizard","sidebar","401","404","multi-tenant"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-009","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T16:11:09Z","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md","userStory":"Como utilizador da CoachID, quero que as contas organizacionais sejam geridas pela própria aplicação (entidade Organização com 1+ utilizadores), com selector na sidebar e escolha pessoal vs organizacional no setup, e que as organizações Auth0 existentes sejam migradas sem impacto perceptível, para deixar de depender das Organizations do Auth0.","acceptanceCriteria":[{"checked":true,"text":"Existe uma entidade **Organização** no sistema (persistida na app), independente das Auth0 Organizations"},{"checked":true,"text":"Uma organização pode ter **1 ou mais utilizadores** (membership)"},{"checked":true,"text":"Contas pessoais e organizacionais continuam a funcionar no resto do produto (equipas, facturação, etc.) com o novo modelo"},{"checked":true,"text":"A aplicação **deixa de utilizar Auth0 Organizations** para gerir contas organizacionais"},{"checked":true,"text":"Existe um **script de migração** que porta todas as organizações existentes no Auth0 para o novo sistema"},{"checked":true,"text":"Após a migração, o utilizador continua a ver as mesmas organizações/contas e memberships — **como se nada tivesse mudado**"},{"checked":true,"text":"O script é idempotente / seguro para reexecução (ou documenta claramente o procedimento one-shot)"},{"checked":true,"text":"Existe um **selector de organização** no canto **inferior esquerdo** da sidebar da aplicação"},{"checked":true,"text":"O utilizador pode **mudar de organização** (e/ou conta pessoal, se aplicável) através desse selector"},{"checked":true,"text":"O contexto activo (rotas, dados, permissões) reflecte a organização seleccionada"},{"checked":true,"text":"No **primeiro passo** do setup wizard, o utilizador pode criar uma **conta pessoal** ou uma **conta organizacional**"},{"checked":true,"text":"O passo explica o **propósito** de cada opção"},{"checked":true,"text":"Cada opção tem **ícones ilustrativos** claros"},{"checked":true,"text":"Existe uma página **404** com botão para retomar / ir para o início da aplicação"},{"checked":true,"text":"Existe uma página **401** que **redirecciona o utilizador para o login**"}],"acceptanceCriteriaRaw":"### Modelo e API\n\n- [x] Existe uma entidade **Organização** no sistema (persistida na app), independente das Auth0 Organizations\n- [x] Uma organização pode ter **1 ou mais utilizadores** (membership)\n- [x] Contas pessoais e organizacionais continuam a funcionar no resto do produto (equipas, facturação, etc.) com o novo modelo\n- [x] A aplicação **deixa de utilizar Auth0 Organizations** para gerir contas organizacionais\n\n### Migração\n\n- [x] Existe um **script de migração** que porta todas as organizações existentes no Auth0 para o novo sistema\n- [x] Após a migração, o utilizador continua a ver as mesmas organizações/contas e memberships — **como se nada tivesse mudado**\n- [x] O script é idempotente / seguro para reexecução (ou documenta claramente o procedimento one-shot)\n\n### Selector de organização\n\n- [x] Existe um **selector de organização** no canto **inferior esquerdo** da sidebar da aplicação\n- [x] O utilizador pode **mudar de organização** (e/ou conta pessoal, se aplicável) através desse selector\n- [x] O contexto activo (rotas, dados, permissões) reflecte a organização seleccionada\n\n### Setup wizard\n\n- [x] No **primeiro passo** do setup wizard, o utilizador pode criar uma **conta pessoal** ou uma **conta organizacional**\n- [x] O passo explica o **propósito** de cada opção\n- [x] Cada opção tem **ícones ilustrativos** claros\n\n### Páginas de erro\n\n- [x] Existe uma página **404** com botão para retomar / ir para o início da aplicação\n- [x] Existe uma página **401** que **redirecciona o utilizador para o login**","tasksMarkdown":"- [T-058](items/T-058-entidade-organizacao-membership-api.md) — Entidade Organização, membership e API (sair das Auth0 Orgs)\n- [T-059](items/T-059-script-migracao-auth0-orgs.md) — Script de migração Auth0 Organizations → sistema próprio\n- [T-060](items/T-060-selector-organizacao-sidebar.md) — Selector de organização na sidebar (canto inferior esquerdo)\n- [T-061](items/T-061-setup-wizard-pessoal-vs-organizacional.md) — Setup wizard — conta pessoal vs organizacional no 1º passo\n- [T-062](items/T-062-paginas-404-e-401.md) — Páginas 404 (botão início) e 401 (redirect login)","children":[{"id":"B-031","title":"Conta organizacional nova não fica em Trial (app)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-031-org-nova-sem-trial-app.md"},{"id":"B-032","title":"Página de facturação em org abre Auth0 consent em vez da UI","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-032-facturacao-org-auth0-consent.md"},{"id":"B-037","title":"Wizard — passo pessoal/org falta no registo e aparece ao criar equipa","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-037-wizard-passo-pessoal-org-registo-vs-nova-equipa.md"},{"id":"T-058","title":"Entidade Organização, membership e API (sair das Auth0 Orgs)","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-058-entidade-organizacao-membership-api.md"},{"id":"T-059","title":"Script de migração Auth0 Organizations → sistema próprio","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-059-script-migracao-auth0-orgs.md"},{"id":"T-060","title":"Selector de organização na sidebar (canto inferior esquerdo)","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-060-selector-organizacao-sidebar.md"},{"id":"T-061","title":"Setup wizard — conta pessoal vs organizacional no 1º passo","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-061-setup-wizard-pessoal-vs-organizacional.md"},{"id":"T-062","title":"Páginas 404 (botão início) e 401 (redirect login)","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-062-paginas-404-e-401.md"}],"promptFeedback":[{"index":"7","when":"2026-08-11T15:50:52Z","kind":"feedback","author":"Marco Mendão","summary":"Verificar se S-017 está completa; marcar done (filhos + AC ok)."},{"index":"3","when":"2026-08-10T07:22:16Z","kind":"prompt","author":"Marco Mendão","summary":"Prioridade máxima (critical) em S-017 e tarefas T-058…T-062."},{"index":"2","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Criar user story e tarefas: decompor S-017 em T-058…T-062 (modelo/API, migração, selector, wizard, 404/401)."},{"index":"1","when":"2026-08-10T07:18:20Z","kind":"prompt","author":"Marco Mendão","summary":"Criar story: deixar Auth0 Orgs; entidade Organização (1+ users); selector sidebar canto inferior esquerdo; migrar orgs Auth0 (script, zero impacto); setup wizard passo 1 pessoal vs org com propósito + ícones; páginas 404 (botão início) e 401 (redirect login)."},{"index":"4","when":"2026-08-10T16:11:09Z","kind":"prompt","author":"Marco Mendão","summary":"Implementar S-017 (T-058…T-062): orgs próprias, migração, selector, wizard, 401/404."},{"index":"5","when":"2026-08-10T16:43:16Z","kind":"prompt","author":"Marco Mendão","summary":"Migration script: prompts Auth0 realm + Mongo URL com defaults .env."},{"index":"6","when":"2026-08-10T16:52:32Z","kind":"prompt","author":"Marco Mendão","summary":"Portar S-017 para worktree-1; org picker igual a team/season, abaixo da época; conta pessoal = Conta de uso Pessoal."}],"commits":[{"sha":"3f57054","repo":"coachid-taskmark","date":"2026-08-10T07:23:49Z","author":"Marco Mendão","message":"log S-017 and T-055 commits"},{"sha":"213ee64","repo":"coachid-taskmark","date":"2026-08-10T07:23:24Z","author":"Marco Mendão","message":"add S-017 organizations board story and tasks"},{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"},{"sha":"0b56ff6","repo":"coachid-taskmark","date":"2026-08-10T17:44:58+01:00","author":"Marco Mendão","message":"update taskmark board for S-017"},{"sha":"26bcd3a","repo":"coachid_app_api","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"seed org app trial and fix admin trial status"},{"sha":"b378b1c","repo":"coachid_app_frontend","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"fix org wizard billing and workspace cookie match"},{"sha":"a1e4dad","repo":"coachid_app_api","date":"2026-08-10T19:37:58+01:00","author":"Marco Mendão","message":"report subscription buckets in auth0 org migration"},{"sha":"665ca7b","repo":"coachid_app_api","date":"2026-08-11T01:02:17+01:00","author":"Marco Mendão","message":"add auth0 management 429 retry backoff"},{"sha":"d8d48d0","repo":"coachid-taskmark","date":"2026-08-11T01:02:18+01:00","author":"Marco Mendão","message":"update taskmark board for auth0 retry"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T16:11:09Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: implementar S-017 organizações próprias. · auto-closed: idle cap (next-day 12:00 UTC); all children done — S-017 complete"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-031-org-nova-sem-trial-app.md":{"id":"B-031","title":"Conta organizacional nova não fica em Trial (app)","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["organizacoes","trial","subscriptions","admin","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T18:20:00Z","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-031-org-nova-sem-trial-app.md","description":"Ao criar uma conta organizacional, a workspace não aparece como **Trial (app)** no admin / estado de subscrição, embora contas pessoais fiquem correctamente em trial.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"Causa: bootstrap de trial só em `registerMe`; admin exige `billingOwnerSub` (null pré-checkout) e classifica `app_trial` sem `trialEndsAt` como inactive.\n\nFix: seed trial em `createOrganization` com `billingOwnerSub` do owner; admin usa `trialEnd` do documento + sentinel para entitlement.","promptFeedback":[{"index":"1","when":"2026-08-10T18:18:17Z","kind":"prompt","author":"Marco Mendão","summary":"Conta org criada não fica Trial(app); facturação abre Auth0 consent."},{"index":"2","when":"2026-08-10T18:22:00Z","kind":"feedback","author":"Marco Mendão","summary":"Seed app_trial na criação da org; admin classifica Trial(app) via trialEnd + billingOwnerSub/sentinel."}],"commits":[{"sha":"26bcd3a","repo":"coachid_app_api","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"seed org app trial and fix admin trial status"},{"sha":"b378b1c","repo":"coachid_app_frontend","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"fix org wizard billing and workspace cookie match"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T18:20:00Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: trial app + billing cookie para orgs. · auto-closed: idle cap (next-day 12:00 UTC); org trial + billing cookie done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-032-facturacao-org-auth0-consent.md":{"id":"B-032","title":"Página de facturação em org abre Auth0 consent em vez da UI","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","billing","auth0","cookie","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T18:20:00Z","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-032-facturacao-org-auth0-consent.md","description":"Numa workspace `org_…`, clicar em Facturação redirecciona para `coachid.eu.auth0.com/u/consent` em vez de mostrar a página de facturação da app.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"`sessionMatchesOrganizationRoute` era chamado sem o cookie activo; mismatch → `redirect(\"/auth/login\")` → Auth0 consent com audience/`offline_access`.\n\nFix: helper `sessionMatchesActiveOrganizationRoute` + redirect `/` em mismatch; layouts/billing/APIs passam a usar o cookie.","promptFeedback":[{"index":"1","when":"2026-08-10T18:18:17Z","kind":"prompt","author":"Marco Mendão","summary":"Conta org criada não fica Trial(app); facturação abre Auth0 consent."},{"index":"2","when":"2026-08-10T18:22:00Z","kind":"feedback","author":"Marco Mendão","summary":"Match de workspace com cookie activo; billing já não redirecciona para Auth0 consent."}],"commits":[{"sha":"b378b1c","repo":"coachid_app_frontend","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"fix org wizard billing and workspace cookie match"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-037-wizard-passo-pessoal-org-registo-vs-nova-equipa.md":{"id":"B-037","title":"Wizard — passo pessoal/org falta no registo e aparece ao criar equipa","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":173000,"tags":["setup-wizard","onboarding","organizacoes","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:21:07Z","completedAt":"2026-08-12T17:24:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-037-wizard-passo-pessoal-org-registo-vs-nova-equipa.md","description":"No registo / wizard de inicialização, o 1º passo (conta pessoal vs organizacional) deve aparecer. Ao criar uma equipa nova já dentro de uma conta, esse passo **não** deve aparecer.","acceptanceCriteria":[{"checked":true,"text":"`!onboarded` → sempre `/onboarding/account` (incl. module-shortcuts)"},{"checked":true,"text":"Onboarding em workspace pessoal sem `accountKind` redirecciona para account"},{"checked":true,"text":"Setup (criar equipa) nunca mostra `/setup/account`; vai a `/setup/team`"},{"checked":true,"text":"Home / ResolveAppHomePath alinhados"}],"acceptanceCriteriaRaw":"- [x] `!onboarded` → sempre `/onboarding/account` (incl. module-shortcuts)\n- [x] Onboarding em workspace pessoal sem `accountKind` redirecciona para account\n- [x] Setup (criar equipa) nunca mostra `/setup/account`; vai a `/setup/team`\n- [x] Home / ResolveAppHomePath alinhados","reproSteps":"","fixCriteria":"- [x] `!onboarded` → sempre `/onboarding/account` (incl. module-shortcuts)\n- [x] Onboarding em workspace pessoal sem `accountKind` redirecciona para account\n- [x] Setup (criar equipa) nunca mostra `/setup/account`; vai a `/setup/team`\n- [x] Home / ResolveAppHomePath alinhados","notes":"Parent: [S-017](../story.md) · Relacionado: [T-061](T-061-setup-wizard-pessoal-vs-organizacional.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:21:07Z","kind":"prompt","author":"Marco Mendão","summary":"No registo deve aparecer pessoal/org; ao criar equipa nova na conta não"},{"index":"2","when":"2026-08-12T17:24:00Z","kind":"feedback","author":"Marco Mendão","summary":"Gate: onboarding força account; setup salta account"},{"index":"3","when":"2026-08-12T17:28:00Z","kind":"prompt","author":"Marco Mendão","summary":"Ainda não aparece o passo — estava em org_* e account saltava para team"},{"index":"4","when":"2026-08-12T17:28:00Z","kind":"feedback","author":"Marco Mendão","summary":"Account step visível também em org_*; login/signup fixa cookie pessoal"}],"commits":[{"sha":"62d8a37","repo":"coachid_app_frontend","date":"2026-08-12T17:50:23Z","author":"Marco Mendão","message":"native logout and auth ui without auth0 hosted pages"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:21:07Z","ended":"2026-08-12T17:24:00Z","summary":"Gate account step: onboarding only; setup → team"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-058-entidade-organizacao-membership-api.md":{"id":"T-058","title":"Entidade Organização, membership e API (sair das Auth0 Orgs)","type":"task","status":"done","priority":"critical","size":"L","points":5,"estimateMinutes":110,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","auth0","api","membership","multi-tenant"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-058-entidade-organizacao-membership-api.md","description":"Introduzir a entidade **Organização** persistida na aplicação (independente das Auth0 Organizations), com membership de **1 ou mais utilizadores**, e adaptar a API/produto para deixar de usar Auth0 Organizations como fonte de verdade das contas organizacionais. Contas pessoais e organizacionais devem continuar a funcionar com o resto do produto (equipas, facturação, etc.).","acceptanceCriteria":[{"checked":true,"text":"Modelo/persistência de **Organização** na app"},{"checked":true,"text":"Membership: uma organização pode ter 1+ utilizadores"},{"checked":true,"text":"API (e contextos existentes) usam a nova entidade em vez de Auth0 Organizations"},{"checked":true,"text":"Contas pessoais e organizacionais continuam a funcionar no resto do produto"},{"checked":true,"text":"A app deixa de depender das Auth0 Organizations para gerir contas organizacionais"}],"acceptanceCriteriaRaw":"- [x] Modelo/persistência de **Organização** na app\n- [x] Membership: uma organização pode ter 1+ utilizadores\n- [x] API (e contextos existentes) usam a nova entidade em vez de Auth0 Organizations\n- [x] Contas pessoais e organizacionais continuam a funcionar no resto do produto\n- [x] A app deixa de depender das Auth0 Organizations para gerir contas organizacionais","reproSteps":"","fixCriteria":"","notes":"Parte de [S-017](../story.md). Coordenar com T-059 (migração) para IDs/slugs e mapeamento Auth0 → novo modelo.","promptFeedback":[{"index":"1","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tasks sob S-017: modelo/API Organização + membership e saída Auth0 Orgs."},{"index":"2","when":"2026-08-10T16:19:03Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of S-017 session (app-owned orgs + membership, migration script, sidebar selector, wizard account step, 404/401)."}],"commits":[{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-059-script-migracao-auth0-orgs.md":{"id":"T-059","title":"Script de migração Auth0 Organizations → sistema próprio","type":"task","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":65,"actualMinutes":66,"actualMs":3961000,"tags":["organizacoes","auth0","migracao","script"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T18:34:32Z","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-059-script-migracao-auth0-orgs.md","description":"Criar um script que porta todas as organizações existentes no Auth0 para o novo sistema de Organizações da app, preservando memberships e identidade das contas, de forma que para o utilizador **nada tenha mudado**.","acceptanceCriteria":[{"checked":true,"text":"Script migra todas as organizações Auth0 existentes para o novo modelo"},{"checked":true,"text":"Memberships / associações de utilizadores são preservadas"},{"checked":true,"text":"Após migração, a experiência do utilizador é equivalente (mesmas orgs/contas)"},{"checked":true,"text":"Script é idempotente / seguro para reexecução, ou o procedimento one-shot está documentado"},{"checked":true,"text":"Por org importada, valida e reporta a subscrição como **active** / **trial** / **inactive** (e faz seed de `app_trial` se ainda não existir)"},{"checked":true,"text":"Auth0 Management client faz retry/backoff em 429 (e pausa entre orgs na migração)"}],"acceptanceCriteriaRaw":"- [x] Script migra todas as organizações Auth0 existentes para o novo modelo\n- [x] Memberships / associações de utilizadores são preservadas\n- [x] Após migração, a experiência do utilizador é equivalente (mesmas orgs/contas)\n- [x] Script é idempotente / seguro para reexecução, ou o procedimento one-shot está documentado\n- [x] Por org importada, valida e reporta a subscrição como **active** / **trial** / **inactive** (e faz seed de `app_trial` se ainda não existir)\n- [x] Auth0 Management client faz retry/backoff em 429 (e pausa entre orgs na migração)","reproSteps":"","fixCriteria":"","notes":"Depende do modelo em T-058. Preferir dry-run / logs claros.\n\nO script pergunta interactivamente (inquirer) por Auth0 realm (domain, client id/secret, roles opcionais) e URL MongoDB; os defaults vêm do `.env`.\n\nBuckets: `active` (Stripe active/past_due ou manual access), `trial` (Stripe trialing ou app_trial em curso), `inactive` (em falta/expirada/cancelada).","promptFeedback":[{"index":"1","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Task migração Auth0 Orgs → sistema próprio sob S-017."},{"index":"2","when":"2026-08-10T16:19:03Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of S-017 session (app-owned orgs + membership, migration script, sidebar selector, wizard account step, 404/401)."},{"index":"3","when":"2026-08-10T16:43:16Z","kind":"prompt","author":"Marco Mendão","summary":"Migration script deve perguntar Auth0 realm + Mongo URL (defaults do .env)."},{"index":"4","when":"2026-08-10T18:34:32Z","kind":"prompt","author":"Marco Mendão","summary":"migrate:auth0-orgs deve validar subscrição active/inactive/trial por org importada."},{"index":"5","when":"2026-08-10T18:36:00Z","kind":"feedback","author":"Marco Mendão","summary":"Script classifica bucket + seed app_trial em falta; resumo active/trial/inactive."},{"index":"6","when":"2026-08-10T23:57:04Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar backoff/retry no client Auth0 Management para 429."},{"index":"7","when":"2026-08-10T23:57:37Z","kind":"feedback","author":"Marco Mendão","summary":"Retry/backoff Auth0 Management para 429 implementado."}],"commits":[{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"},{"sha":"a1e4dad","repo":"coachid_app_api","date":"2026-08-10T19:37:58+01:00","author":"Marco Mendão","message":"report subscription buckets in auth0 org migration"},{"sha":"665ca7b","repo":"coachid_app_api","date":"2026-08-11T01:02:17+01:00","author":"Marco Mendão","message":"add auth0 management 429 retry backoff"},{"sha":"d8d48d0","repo":"coachid-taskmark","date":"2026-08-11T01:02:18+01:00","author":"Marco Mendão","message":"update taskmark board for auth0 retry"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T18:34:32Z","ended":"2026-08-10T19:40:00Z","summary":"Subscription bucket validation + app_trial seed in migrate:auth0-orgs."},{"session":"2","actor":"Marco Mendão","started":"2026-08-10T23:57:04Z","ended":"2026-08-10T23:57:37Z","summary":"Auth0 Management 429/5xx retry with backoff + org pause in migrate script."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-060-selector-organizacao-sidebar.md":{"id":"T-060","title":"Selector de organização na sidebar (canto inferior esquerdo)","type":"task","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":65,"actualMinutes":0,"actualMs":0,"tags":["organizacoes","sidebar","selector","frontend","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-060-selector-organizacao-sidebar.md","description":"Adicionar na sidebar da aplicação, no canto **inferior esquerdo**, um selector que permita ao utilizador mudar de organização (e conta pessoal, se aplicável). O contexto activo (rotas, dados, permissões) deve reflectir a selecção.","acceptanceCriteria":[{"checked":true,"text":"Selector visível no canto inferior esquerdo da sidebar"},{"checked":true,"text":"Utilizador consegue mudar de organização (e/ou conta pessoal se aplicável)"},{"checked":true,"text":"Contexto activo (rotas, dados, permissões) reflecte a organização seleccionada"}],"acceptanceCriteriaRaw":"- [x] Selector visível no canto inferior esquerdo da sidebar\n- [x] Utilizador consegue mudar de organização (e/ou conta pessoal se aplicável)\n- [x] Contexto activo (rotas, dados, permissões) reflecte a organização seleccionada","reproSteps":"","fixCriteria":"","notes":"Parte de [S-017](../story.md). Depende do modelo/API em T-058.","promptFeedback":[{"index":"1","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Task selector org sidebar sob S-017."},{"index":"2","when":"2026-08-10T16:19:03Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of S-017 session (app-owned orgs + membership, migration script, sidebar selector, wizard account step, 404/401)."},{"index":"3","when":"2026-08-10T16:53:46Z","kind":"feedback","author":"Marco Mendão","summary":"worktree-1: org picker alinhado a team/season, abaixo da época; label pessoal = Conta de uso Pessoal."},{"index":"4","when":"2026-08-10T17:58:33Z","kind":"prompt","author":"Marco Mendão","summary":"Org picker redireciona para /org_… e dá 404."},{"index":"5","when":"2026-08-10T17:58:51Z","kind":"feedback","author":"Marco Mendão","summary":"Org switch usa ResolveAppHomePath (evita 404 em /org_…)."},{"index":"6","when":"2026-08-10T18:03:54Z","kind":"prompt","author":"Marco Mendão","summary":"Ao mudar de organização o conteúdo da app deve ficar em loading."},{"index":"7","when":"2026-08-10T18:04:31Z","kind":"feedback","author":"Marco Mendão","summary":"Overlay de loading full-screen ao mudar de organização."}],"commits":[{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-061-setup-wizard-pessoal-vs-organizacional.md":{"id":"T-061","title":"Setup wizard — conta pessoal vs organizacional no 1º passo","type":"task","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["setup-wizard","onboarding","organizacoes","ux","frontend"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T17:02:10Z","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-061-setup-wizard-pessoal-vs-organizacional.md","description":"No primeiro passo do setup wizard, permitir criar uma **conta pessoal** ou **conta organizacional**, explicando o propósito de cada opção e usando ícones ilustrativos claros.","acceptanceCriteria":[{"checked":true,"text":"No 1º passo do setup, o utilizador escolhe conta pessoal ou organizacional"},{"checked":true,"text":"O passo explica o propósito de cada opção"},{"checked":true,"text":"Cada opção tem ícones ilustrativos claros"},{"checked":true,"text":"A escolha cria / inicia o fluxo correcto no novo modelo de contas"}],"acceptanceCriteriaRaw":"- [x] No 1º passo do setup, o utilizador escolhe conta pessoal ou organizacional\n- [x] O passo explica o propósito de cada opção\n- [x] Cada opção tem ícones ilustrativos claros\n- [x] A escolha cria / inicia o fluxo correcto no novo modelo de contas","reproSteps":"","fixCriteria":"","notes":"Parte de [S-017](../story.md). Alinhar com T-058 (criação de Organização vs conta pessoal).\n\nFluxo organizacional: account → org-details → org-members → team → season → lineup → ready (rever; cria org+equipa só ao confirmar).","promptFeedback":[{"index":"1","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Task setup wizard pessoal vs org sob S-017."},{"index":"2","when":"2026-08-10T16:19:03Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of S-017 session (app-owned orgs + membership, migration script, sidebar selector, wizard account step, 404/401)."},{"index":"3","when":"2026-08-10T17:02:10Z","kind":"prompt","author":"Marco Mendão","summary":"Wizard criar org deve fazer parte do setup/onboarding inicial (não wizard separado)."},{"index":"4","when":"2026-08-10T17:05:57Z","kind":"feedback","author":"Marco Mendão","summary":"Create-org steps (details/members/summary) now live inside onboarding/setup; after create continues to team in same wizard. Standalone /create-organization kept for sidebar/pricing → setup/team."},{"index":"5","when":"2026-08-10T17:06:53Z","kind":"prompt","author":"Marco Mendão","summary":"Passo Rever da org deve fazer parte do passo Pronto no wizard inicial."},{"index":"6","when":"2026-08-10T17:08:59Z","kind":"feedback","author":"Marco Mendão","summary":"Removido passo Rever separado; org criada e revista no passo Pronto do wizard."},{"index":"7","when":"2026-08-10T17:40:46Z","kind":"prompt","author":"Marco Mendão","summary":"Avançar passo 2→3 volta ao passo 2 (race setState/navegação)."},{"index":"8","when":"2026-08-10T17:41:21Z","kind":"feedback","author":"Marco Mendão","summary":"Fix bounce 2→3: flushSync no nome da org + guard adiado em org-members."},{"index":"9","when":"2026-08-10T17:42:30Z","kind":"prompt","author":"Marco Mendão","summary":"next-intl missing context + double-encode auth0"},{"index":"10","when":"2026-08-10T17:42:37Z","kind":"feedback","author":"Marco Mendão","summary":"wizardBasePath sem encodeURIComponent (evita %257C e 500 next-intl)."},{"index":"11","when":"2026-08-10T17:42:48Z","kind":"prompt","author":"Marco Mendão","summary":"Só criar equipa e organização no final do setup wizard."},{"index":"12","when":"2026-08-10T17:44:31Z","kind":"feedback","author":"Marco Mendão","summary":"Pronto é review explícito; org+equipa só no confirmar. CTA equipa = Continuar."},{"index":"13","when":"2026-08-10T17:46:01Z","kind":"prompt","author":"Marco Mendão","summary":"Passo 4 (equipa) deve permitir voltar atrás."},{"index":"14","when":"2026-08-10T17:46:21Z","kind":"feedback","author":"Marco Mendão","summary":"Passo equipa com Voltar → org-members (org) ou account (pessoal)."},{"index":"15","when":"2026-08-10T17:48:18Z","kind":"prompt","author":"Marco Mendão","summary":"Picker de acordos legais deve estar no último passo do wizard."},{"index":"16","when":"2026-08-10T17:49:12Z","kind":"feedback","author":"Marco Mendão","summary":"Acordos legais movidos do passo equipa para o Pronto (review)."},{"index":"17","when":"2026-08-10T17:50:38Z","kind":"prompt","author":"Marco Mendão","summary":"Voltar do passo 7 deixa Continuar do passo 6 locked com spinner."},{"index":"18","when":"2026-08-10T17:51:08Z","kind":"feedback","author":"Marco Mendão","summary":"Fix Continuar locked: lineup já não seta wizardCompleting ao ir para Pronto."},{"index":"19","when":"2026-08-10T17:53:07Z","kind":"prompt","author":"Marco Mendão","summary":"Texto page.onboarding.team.cta.back não aparece."},{"index":"20","when":"2026-08-10T17:53:07Z","kind":"feedback","author":"Marco Mendão","summary":"Voltar na equipa usa common.back (igual aos outros passos)."},{"index":"21","when":"2026-08-10T17:55:34Z","kind":"prompt","author":"Marco Mendão","summary":"Passo 7: cartões Org+Contexto e Equipa+Plantel lado a lado."},{"index":"22","when":"2026-08-10T17:56:17Z","kind":"feedback","author":"Marco Mendão","summary":"Pronto: grelha Org"},{"index":"23","when":"2026-08-10T18:07:11Z","kind":"prompt","author":"Marco Mendão","summary":"Botão Voltar no passo equipa só no setup inicial (não ao criar equipa em org existente)."},{"index":"24","when":"2026-08-10T18:08:31Z","kind":"prompt","author":"Marco Mendão","summary":"Criar equipa em org existente: sem Voltar; progresso começa em Equipa (sem Conta/Org/Membros)."},{"index":"25","when":"2026-08-10T18:09:57Z","kind":"feedback","author":"Marco Mendão","summary":"org_…: progresso Equipa→…; sem Conta/Org/Membros; Voltar só no setup inicial."}],"commits":[{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"},{"sha":"b378b1c","repo":"coachid_app_frontend","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"fix org wizard billing and workspace cookie match"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T17:02:10Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: integrar create-org no setup wizard. · auto-closed: idle cap (next-day 12:00 UTC); wizard pessoal/org done"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-062-paginas-404-e-401.md":{"id":"T-062","title":"Páginas 404 (botão início) e 401 (redirect login)","type":"task","status":"done","priority":"critical","size":"S","points":2,"estimateMinutes":45,"actualMinutes":0,"actualMs":0,"tags":["404","401","frontend","auth","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-017","epic":"E-009","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"","completedAt":"2026-08-11T15:50:52Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-062-paginas-404-e-401.md","description":"Adicionar página **404** com botão para retomar / ir para o início da aplicação, e página **401** que redirecciona o utilizador para o login.","acceptanceCriteria":[{"checked":true,"text":"Página 404 com botão para o início da aplicação"},{"checked":true,"text":"Página 401 redirecciona para o login"},{"checked":true,"text":"Rotas/handlers cobrem os casos de not-found e unauthorized na app"}],"acceptanceCriteriaRaw":"- [x] Página 404 com botão para o início da aplicação\n- [x] Página 401 redirecciona para o login\n- [x] Rotas/handlers cobrem os casos de not-found e unauthorized na app","reproSteps":"","fixCriteria":"","notes":"Parte de [S-017](../story.md). Pode ser entregue em paralelo com o resto da story.","promptFeedback":[{"index":"1","when":"2026-08-10T07:19:57Z","kind":"prompt","author":"Marco Mendão","summary":"Task páginas 404/401 sob S-017."},{"index":"2","when":"2026-08-10T16:19:03Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of S-017 session (app-owned orgs + membership, migration script, sidebar selector, wizard account step, 404/401)."}],"commits":[{"sha":"afa9545","repo":"coachid_app_api","date":"2026-08-10T17:44:46+01:00","author":"Marco Mendão","message":"add organization membership api and auth0 migration"},{"sha":"c54f1f1","repo":"coachid_app_frontend","date":"2026-08-10T17:44:47+01:00","author":"Marco Mendão","message":"add org selector wizard and app-owned workspaces"}],"workLog":[]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/epic.md":{"id":"E-010","title":"Pagamentos","type":"epic","status":"done","priority":"high","size":"—","points":34,"estimateMinutes":5302,"actualMinutes":5282,"actualMs":316969000,"tags":["module","pagamentos","facturacao","stripe","billing"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-30T23:46:32Z","completedAt":"2026-08-03T15:57:46Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/epic.md","goal":"Permitir que cada conta (pessoal ou organização) tenha definições de facturação completas, sincronizadas com o Stripe, com aviso quando a subscrição está activa sem dados fiscais, e acesso às facturas emitidas.","scope":"- Página de definições de facturação por conta (pessoal / organização)\n- Formulário fiscal (nome, morada, empresa, NIF, país) com pré-preenchimento e sync Stripe\n- Dialog CTA quando há subscrição activa sem dados de facturação\n- Listagem de facturas (Stripe) na página de facturação","outOfScope":"- Portal de pagamento / checkout (já existente)\n- Facturação local própria (PDF CoachID) — nesta fase só facturas Stripe\n- Multi-moeda avançada ou crédito fiscal além do NIF","successMetrics":"- Contas com subscrição activa têm caminho claro para completar facturação\n- Alterações de facturação reflectem-se no customer Stripe\n- Utilizador vê as suas facturas Stripe na página de definições","storiesMarkdown":"- [S-012](stories/S-012-definicoes-facturacao-por-conta/story.md) — Página de definições de facturação por conta (formulário + sync Stripe)\n- [S-013](stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md) — Dialog CTA quando subscrição activa sem dados de facturação\n- [S-014](stories/S-014-listagem-facturas-stripe/story.md) — Listagem de facturas Stripe na página de facturação","children":[{"id":"S-012","title":"Página de definições de facturação por conta (formulário + sync Stripe)","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md"},{"id":"S-013","title":"Dialog CTA quando subscrição activa sem dados de facturação","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md"},{"id":"S-014","title":"Listagem de facturas Stripe na página de facturação","type":"story","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md"}],"commits":[{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"},{"sha":"ec40381","repo":"coachid_app_frontend","date":"2026-07-31T16:22:42Z","author":"Marco Mendão","message":"add cancel button to billing checkout modal"},{"sha":"3f97c00","repo":"coachid_app_frontend","date":"2026-07-31T16:21:58Z","author":"Marco Mendão","message":"preselect billing country from team"},{"sha":"719d881","repo":"coachid_app_frontend","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"require billing form before stripe checkout"},{"sha":"09b5c02","repo":"coachid_app_api","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"reject checkout when billing profile incomplete"},{"sha":"59a72ef","repo":"coachid_app_frontend","date":"2026-07-31T16:14:00Z","author":"Marco Mendão","message":"hide billing profile dialog until account has a team"},{"sha":"aba72e2","repo":"coachid-taskmark","date":"2026-07-31T15:59:17Z","author":"Marco Mendão","message":"update E-010 billing board"},{"sha":"d42d55d","repo":"coachid_app_api","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"fix billing stripe name sync and validation"},{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"},{"sha":"13659cb","repo":"coachid-taskmark","date":"2026-07-30T23:33:30+01:00","author":"Marco Mendão","message":"refresh INDEX with E-010 pagamentos"},{"sha":"70d73e6","repo":"coachid-taskmark","date":"2026-07-30T23:33:07+01:00","author":"Marco Mendão","message":"add E-010 pagamentos billing stories"},{"sha":"ad0d17e","repo":"coachid_app_api","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile and stripe invoices api"},{"sha":"13f4ccd","repo":"coachid_app_frontend","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile page and completion cta"},{"sha":"984ec59","repo":"coachid-taskmark","date":"2026-07-31T06:41:00Z","author":"Marco Mendão","message":"update E-010 pagamentos board"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-30T23:46:32Z","ended":"2026-07-31T12:00:00Z","summary":"In progress: implement E-010 billing settings, CTA, invoices. — auto-closed: idle cap / parent complete"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md":{"id":"S-012","title":"Página de definições de facturação por conta (formulário + sync Stripe)","type":"story","status":"done","priority":"high","size":"XL","points":27,"estimateMinutes":4320,"actualMinutes":4320,"actualMs":259200000,"tags":["pagamentos","facturacao","stripe","settings","billing"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-010","epic":"E-010","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-30T23:46:32Z","completedAt":"2026-08-03T15:57:46Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md","userStory":"Como titular de conta (pessoal ou organização), quero uma página de definições de facturação por cada conta associada a mim, com os meus dados fiscais pré-preenchidos quando possível, e que ao guardar actualize também o Stripe, para emitir facturas correctas.","acceptanceCriteria":[{"checked":true,"text":"Existe uma página de configuração de facturação **por conta** (conta pessoal ou conta de organização)"},{"checked":true,"text":"Um utilizador com várias contas associadas tem **uma definição de facturação por conta** (não uma única global)"},{"checked":true,"text":"O formulário permite definir: nome, morada, se é empresa ou não; se empresa → nome da empresa; NIF (empresa ou pessoal); país de facturação"},{"checked":true,"text":"Nome e email são **pré-preenchidos** automaticamente com o nome da conta e o email da conta do utilizador (editáveis se fizer sentido no produto)"},{"checked":true,"text":"Ao guardar/alterar os dados de facturação, as informações são **actualizadas no Stripe** (customer / tax / address conforme o modelo actual)"},{"checked":true,"text":"Validação básica dos campos obrigatórios e feedback de sucesso/erro"}],"acceptanceCriteriaRaw":"- [x] Existe uma página de configuração de facturação **por conta** (conta pessoal ou conta de organização)\n- [x] Um utilizador com várias contas associadas tem **uma definição de facturação por conta** (não uma única global)\n- [x] O formulário permite definir: nome, morada, se é empresa ou não; se empresa → nome da empresa; NIF (empresa ou pessoal); país de facturação\n- [x] Nome e email são **pré-preenchidos** automaticamente com o nome da conta e o email da conta do utilizador (editáveis se fizer sentido no produto)\n- [x] Ao guardar/alterar os dados de facturação, as informações são **actualizadas no Stripe** (customer / tax / address conforme o modelo actual)\n- [x] Validação básica dos campos obrigatórios e feedback de sucesso/erro","tasksMarkdown":"- [T-040](items/T-040-copy-botoes-pagina-facturacao.md) — Copy dos botões na página de facturação\n\n- [T-039](items/T-039-modal-facturacao-botao-cancelar.md) — Modal dados de faturação — botão Cancelar\n\n- [T-038](items/T-038-preseleccionar-pais-facturacao-da-equipa.md) — Pré-seleccionar país de facturação com o país da equipa\n\n- [T-037](items/T-037-checkout-requer-formulario-facturacao.md) — Checkout — recolher dados de facturação antes do Stripe\n\n- [B-017](items/B-017-formulario-facturacao-botao-guardar-desabilitado.md) — Formulário de facturação — botão Guardar fica sempre desabilitado\n- [B-018](items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md) — Facturação — nome da empresa sobrescreve o nome da conta no Stripe\n- [B-033](items/B-033-modal-facturacao-erros-antes-submit.md) — Modal facturação — inputs Empresa mostram erro antes do submit\n- [T-035](items/T-035-formulario-toggle-particular-empresa.md) — Formulário facturação — toggle particular/empresa com campos condicionais\n- [T-036](items/T-036-campos-opcionais-particular-obrigatorios-empresa.md) — Facturação — campos opcionais para particular, obrigatórios para empresa","children":[{"id":"B-017","title":"Formulário de facturação — botão Guardar fica sempre desabilitado","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-017-formulario-facturacao-botao-guardar-desabilitado.md"},{"id":"B-018","title":"Facturação — nome da empresa vs nome da conta no sync Stripe","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md"},{"id":"B-033","title":"Modal facturação — inputs Empresa mostram erro antes do submit","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-033-modal-facturacao-erros-antes-submit.md"},{"id":"T-035","title":"Formulário facturação — toggle particular/empresa com campos condicionais","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-035-formulario-toggle-particular-empresa.md"},{"id":"T-036","title":"Facturação — campos opcionais para particular, obrigatórios para empresa","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-036-campos-opcionais-particular-obrigatorios-empresa.md"},{"id":"T-037","title":"Checkout — recolher dados de facturação antes do Stripe","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-037-checkout-requer-formulario-facturacao.md"},{"id":"T-038","title":"Pré-seleccionar país de facturação com o país da equipa","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-038-preseleccionar-pais-facturacao-da-equipa.md"},{"id":"T-039","title":"Modal dados de faturação — botão Cancelar","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-039-modal-facturacao-botao-cancelar.md"},{"id":"T-040","title":"Copy dos botões na página de facturação","type":"task","status":"done","priority":"low","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-040-copy-botoes-pagina-facturacao.md"}],"promptFeedback":[{"index":"1","when":"2026-07-30T22:32:01Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic Pagamentos — página facturação por conta; formulário fiscal; sync Stripe."},{"index":"2","when":"2026-07-30T23:46:32Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — implementa a E-010 (S-012/S-013/S-014)."}],"commits":[{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"},{"sha":"ec40381","repo":"coachid_app_frontend","date":"2026-07-31T16:22:42Z","author":"Marco Mendão","message":"add cancel button to billing checkout modal"},{"sha":"3f97c00","repo":"coachid_app_frontend","date":"2026-07-31T16:21:58Z","author":"Marco Mendão","message":"preselect billing country from team"},{"sha":"719d881","repo":"coachid_app_frontend","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"require billing form before stripe checkout"},{"sha":"09b5c02","repo":"coachid_app_api","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"reject checkout when billing profile incomplete"},{"sha":"d42d55d","repo":"coachid_app_api","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"fix billing stripe name sync and validation"},{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"},{"sha":"ad0d17e","repo":"coachid_app_api","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile and stripe invoices api"},{"sha":"13f4ccd","repo":"coachid_app_frontend","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile page and completion cta"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:57:46Z","ended":"2026-08-03T15:57:46Z","summary":"rollup: all children done (8 kids)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-017-formulario-facturacao-botao-guardar-desabilitado.md":{"id":"B-017","title":"Formulário de facturação — botão Guardar fica sempre desabilitado","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","rhf","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T06:46:45Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-017-formulario-facturacao-botao-guardar-desabilitado.md","description":"Na página de definições de facturação (`/billing/profile`), após preencher ou alterar os dados, o botão **Guardar** permanece desabilitado. O submit fica bloqueado por `!form.formState.isValid` no RHF, o que impede gravar mesmo com o formulário completo/alterado.","acceptanceCriteria":[{"checked":true,"text":"Após alterar dados de facturação, o botão Guardar fica habilitado (quando há alterações)"},{"checked":true,"text":"Validação continua a correr no submit e mostra erros de campos inválidos"},{"checked":true,"text":"Fluxo de guardar continua a sincronizar com a API/Stripe quando o formulário é válido"}],"acceptanceCriteriaRaw":"- [x] Após alterar dados de facturação, o botão Guardar fica habilitado (quando há alterações)\n- [x] Validação continua a correr no submit e mostra erros de campos inválidos\n- [x] Fluxo de guardar continua a sincronizar com a API/Stripe quando o formulário é válido","reproSteps":"1. Abrir a página de facturação da conta (com ou sem perfil fiscal prévio).\n2. Preencher ou alterar campos obrigatórios (nome, email, morada, país, NIF, etc.).\n3. Observar o botão Guardar.","fixCriteria":"- [x] Após alterar dados de facturação, o botão Guardar fica habilitado (quando há alterações)\n- [x] Validação continua a correr no submit e mostra erros de campos inválidos\n- [x] Fluxo de guardar continua a sincronizar com a API/Stripe quando o formulário é válido","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T06:46:45Z","kind":"prompt","author":"Marco Mendão","summary":"worktree-1: botão Guardar do formulário de facturação sempre desabilitado após alterar dados."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T06:46:45Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: fix billing profile save button disabled state. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md":{"id":"B-018","title":"Facturação — nome da empresa vs nome da conta no sync Stripe","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","stripe","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T07:25:57Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md","description":"No Stripe Dashboard, **Nome de empresa** e **Nome individual** são campos first-class (`business_name` / `individual_name`). Ambos devem ser preenchidos a partir do formulário de facturação: conta → individual, empresa → business. O cabeçalho `name` segue a empresa quando existe.","acceptanceCriteria":[{"checked":true,"text":"Stripe `individual_name` = nome da conta do formulário"},{"checked":true,"text":"Stripe `business_name` = nome da empresa quando “É uma empresa” (limpo caso contrário)"},{"checked":true,"text":"Stripe `customer.name` (cabeçalho) = empresa ou individual"},{"checked":true,"text":"API Stripe client usa versão clover que expõe estes campos"},{"checked":true,"text":"Labels do formulário distinguem nome da conta vs nome da empresa"}],"acceptanceCriteriaRaw":"- [x] Stripe `individual_name` = nome da conta do formulário\n- [x] Stripe `business_name` = nome da empresa quando “É uma empresa” (limpo caso contrário)\n- [x] Stripe `customer.name` (cabeçalho) = empresa ou individual\n- [x] API Stripe client usa versão clover que expõe estes campos\n- [x] Labels do formulário distinguem nome da conta vs nome da empresa","reproSteps":"1. Guardar perfil com nome da conta e (se aplicável) nome da empresa.\n2. No Stripe customer, em Detalhes: Nome de empresa e Nome individual devem estar preenchidos (não \"—\").","fixCriteria":"- [x] Stripe `individual_name` = nome da conta do formulário\n- [x] Stripe `business_name` = nome da empresa quando “É uma empresa” (limpo caso contrário)\n- [x] Stripe `customer.name` (cabeçalho) = empresa ou individual\n- [x] API Stripe client usa versão clover que expõe estes campos\n- [x] Labels do formulário distinguem nome da conta vs nome da empresa","notes":"Worktree: `worktree-1` (API). Reiniciar/aguardar reload da API e voltar a guardar o perfil.","promptFeedback":[{"index":"1","when":"2026-07-31T07:25:57Z","kind":"prompt","author":"Marco Mendão","summary":"Ao mudar o nome da empresa devia mudar o nome da empresa e não o nome da conta."},{"index":"2","when":"2026-07-31T07:33:49Z","kind":"prompt","author":"Marco Mendão","summary":"Alterei o nome da empresa mas esta não alterou no Stripe — validar."},{"index":"3","when":"2026-07-31T07:38:29Z","kind":"prompt","author":"Marco Mendão","summary":"Screenshot: Nome de empresa e Nome individual vazios; preencher ambos."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"d42d55d","repo":"coachid_app_api","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"fix billing stripe name sync and validation"},{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T07:25:57Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: sync Stripe business_name + individual_name. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-033-modal-facturacao-erros-antes-submit.md":{"id":"B-033","title":"Modal facturação — inputs Empresa mostram erro antes do submit","type":"bug","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","rhf","bug","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-08-10","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T18:24:26Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-033-modal-facturacao-erros-antes-submit.md","description":"No formulário/modal de facturação, ao escolher **Empresa**, os campos obrigatórios aparecem logo com erro. Os erros só devem surgir depois de o formulário ser submetido, alinhado com o padrão RHF dos outros formulários da app.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"`BillingProfileForm` usava `mode: \"onChange\"` + `form.trigger()` no toggle `isCompany`.\n\nFix: `mode: \"onSubmit\"` + `reValidateMode: \"onChange\"`; remover trigger; toggle Empresa sem validar até submit.","promptFeedback":[{"index":"1","when":"2026-08-10T18:24:26Z","kind":"prompt","author":"Marco Mendão","summary":"Modal facturação: Empresa mostra erros nos inputs antes do submit; alinhar RHF."},{"index":"2","when":"2026-08-10T18:26:00Z","kind":"feedback","author":"Marco Mendão","summary":"Erros só após submit; toggle Empresa já não dispara validação imediata."},{"index":"3","when":"2026-08-10T18:25:56Z","kind":"prompt","author":"Marco Mendão","summary":"Cancelar e Guardar e continuar devem ser o footer da modal."},{"index":"4","when":"2026-08-10T18:26:30Z","kind":"feedback","author":"Marco Mendão","summary":"Botões no DialogFooter sticky; campos scrolláveis no body."},{"index":"5","when":"2026-08-10T18:27:00Z","kind":"prompt","author":"Marco Mendão","summary":"Particular por defeito: não consegue continuar (Guardar desabilitado)."},{"index":"6","when":"2026-08-10T18:27:20Z","kind":"feedback","author":"Marco Mendão","summary":"Modal: submit activo sem isDirty (defaults particular pré-preenchidos)."}],"commits":[{"sha":"b378b1c","repo":"coachid_app_frontend","date":"2026-08-10T19:31:51+01:00","author":"Marco Mendão","message":"fix org wizard billing and workspace cookie match"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T18:24:26Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: erros facturação só após submit. · auto-closed: idle cap (next-day 12:00 UTC); company field errors only after submit"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-035-formulario-toggle-particular-empresa.md":{"id":"T-035","title":"Formulário facturação — toggle particular/empresa com campos condicionais","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T07:45:51Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-035-formulario-toggle-particular-empresa.md","description":"A primeira opção do formulário de facturação deve ser um toggle (ícone + título + descrição) entre **particular** e **empresa**. Particular: nome do cliente (pré-preenchido com o nome do utilizador). Empresa: nome da empresa + nome do responsável (pré-preenchido com o nome do utilizador).","acceptanceCriteria":[{"checked":true,"text":"Toggle particular/empresa é o primeiro controlo (ícone, título, descrição)"},{"checked":true,"text":"Particular: campo “nome do cliente”, pré-preenchido com o nome do user da conta"},{"checked":true,"text":"Empresa: campos “nome da empresa” e “nome do responsável” (responsável pré-preenchido com o nome do user)"},{"checked":true,"text":"i18n EN/PT"}],"acceptanceCriteriaRaw":"- [x] Toggle particular/empresa é o primeiro controlo (ícone, título, descrição)\n- [x] Particular: campo “nome do cliente”, pré-preenchido com o nome do user da conta\n- [x] Empresa: campos “nome da empresa” e “nome do responsável” (responsável pré-preenchido com o nome do user)\n- [x] i18n EN/PT","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T07:45:51Z","kind":"prompt","author":"Marco Mendão","summary":"Toggle particular/empresa primeiro; particular→nome cliente; empresa→nome empresa + responsável."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T07:45:51Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: billing type toggle + conditional name fields. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-036-campos-opcionais-particular-obrigatorios-empresa.md":{"id":"T-036","title":"Facturação — campos opcionais para particular, obrigatórios para empresa","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","validation"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T07:50:23Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-036-campos-opcionais-particular-obrigatorios-empresa.md","description":"No formulário de facturação, se o utilizador escolhe **particular**, os campos de facturação são opcionais. Se escolhe **empresa**, todos os campos são obrigatórios.","acceptanceCriteria":[{"checked":true,"text":"Particular: nome do cliente + email obrigatórios; restantes campos opcionais"},{"checked":true,"text":"Empresa: todos os campos relevantes são obrigatórios (incl. nome empresa, responsável, email, morada, país, NIF)"},{"checked":true,"text":"Validação alinhada no frontend e na API; `billingProfileComplete` reflecte as mesmas regras"},{"checked":true,"text":"Sync Stripe tolera perfil particular parcial"}],"acceptanceCriteriaRaw":"- [x] Particular: nome do cliente + email obrigatórios; restantes campos opcionais\n- [x] Empresa: todos os campos relevantes são obrigatórios (incl. nome empresa, responsável, email, morada, país, NIF)\n- [x] Validação alinhada no frontend e na API; `billingProfileComplete` reflecte as mesmas regras\n- [x] Sync Stripe tolera perfil particular parcial","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1` (frontend + API).","promptFeedback":[{"index":"1","when":"2026-07-31T07:50:23Z","kind":"prompt","author":"Marco Mendão","summary":"Campos de facturação opcionais para particular; tudo obrigatório para empresa."},{"index":"2","when":"2026-07-31T07:58:00Z","kind":"prompt","author":"Marco Mendão","summary":"Em caso particular o email deve ser sempre obrigatório."},{"index":"3","when":"2026-07-31T15:53:00Z","kind":"prompt","author":"Marco Mendão","summary":"Em caso particular o nome do cliente deve ser obrigatório."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"d42d55d","repo":"coachid_app_api","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"fix billing stripe name sync and validation"},{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T07:50:23Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: optional fields for individual billing, required for company. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-037-checkout-requer-formulario-facturacao.md":{"id":"T-037","title":"Checkout — recolher dados de facturação antes do Stripe","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","checkout","stripe","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:14:22Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-037-checkout-requer-formulario-facturacao.md","description":"Na página de facturação, ao clicar **Continuar para o checkout** (subscrever um plano), se o perfil de facturação estiver incompleto, mostrar primeiro o formulário de dados fiscais. Depois de guardar com sucesso, continuar o checkout Stripe normalmente.","acceptanceCriteria":[{"checked":true,"text":"Com perfil de facturação incompleto, o CTA de checkout abre o formulário (não redirecciona logo para o Stripe)"},{"checked":true,"text":"Após guardar dados de facturação válidos, o fluxo de checkout Stripe inicia normalmente"},{"checked":true,"text":"Com perfil já completo, o checkout inicia de imediato (sem formulário intermédio)"},{"checked":true,"text":"O formulário reutiliza as mesmas regras/validação da página de definições de facturação"}],"acceptanceCriteriaRaw":"- [x] Com perfil de facturação incompleto, o CTA de checkout abre o formulário (não redirecciona logo para o Stripe)\n- [x] Após guardar dados de facturação válidos, o fluxo de checkout Stripe inicia normalmente\n- [x] Com perfil já completo, o checkout inicia de imediato (sem formulário intermédio)\n- [x] O formulário reutiliza as mesmas regras/validação da página de definições de facturação","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`. Entry: `PricingLanding` / `EmbeddedCheckoutButton` + `BillingProfileForm`.","promptFeedback":[{"index":"1","when":"2026-07-31T16:14:22Z","kind":"prompt","author":"Marco Mendão","summary":"Checkout deve mostrar formulário de facturação antes de continuar para o Stripe."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"719d881","repo":"coachid_app_frontend","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"require billing form before stripe checkout"},{"sha":"09b5c02","repo":"coachid_app_api","date":"2026-07-31T16:15:27Z","author":"Marco Mendão","message":"reject checkout when billing profile incomplete"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:14:22Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: gate checkout behind billing profile form. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-038-preseleccionar-pais-facturacao-da-equipa.md":{"id":"T-038","title":"Pré-seleccionar país de facturação com o país da equipa","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","form","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:21:14Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-038-preseleccionar-pais-facturacao-da-equipa.md","description":"No formulário de facturação, o campo **país** deve vir pré-seleccionado com o país da equipa configurada no contexto actual (quando ainda não houver país guardado no perfil de facturação).","acceptanceCriteria":[{"checked":true,"text":"Com perfil sem país, o formulário pré-selecciona o `cca2` da equipa da rota"},{"checked":true,"text":"Se o perfil já tiver país, esse valor prevalece"},{"checked":true,"text":"O mesmo comportamento aplica-se ao formulário no dialog pré-checkout"}],"acceptanceCriteriaRaw":"- [x] Com perfil sem país, o formulário pré-selecciona o `cca2` da equipa da rota\n- [x] Se o perfil já tiver país, esse valor prevalece\n- [x] O mesmo comportamento aplica-se ao formulário no dialog pré-checkout","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T16:21:14Z","kind":"prompt","author":"Marco Mendão","summary":"Pré-seleccionar país de facturação com o país da equipa."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"3f97c00","repo":"coachid_app_frontend","date":"2026-07-31T16:21:58Z","author":"Marco Mendão","message":"preselect billing country from team"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:21:14Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: default billing country from team. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-039-modal-facturacao-botao-cancelar.md":{"id":"T-039","title":"Modal dados de faturação — botão Cancelar","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","dialog","ux"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:22:25Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-039-modal-facturacao-botao-cancelar.md","description":"Na modal **Dados de faturação** (pré-checkout), adicionar um botão **Cancelar** que fecha a modal sem iniciar o checkout.","acceptanceCriteria":[{"checked":true,"text":"A modal tem um botão Cancelar visível junto à acção primária"},{"checked":true,"text":"Cancelar fecha a modal sem guardar nem redireccionar para o Stripe"}],"acceptanceCriteriaRaw":"- [x] A modal tem um botão Cancelar visível junto à acção primária\n- [x] Cancelar fecha a modal sem guardar nem redireccionar para o Stripe","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T16:22:25Z","kind":"prompt","author":"Marco Mendão","summary":"Adicionar botão Cancelar na modal Dados de faturação."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"ec40381","repo":"coachid_app_frontend","date":"2026-07-31T16:22:42Z","author":"Marco Mendão","message":"add cancel button to billing checkout modal"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:22:25Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: add cancel button to billing checkout modal. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-040-copy-botoes-pagina-facturacao.md":{"id":"T-040","title":"Copy dos botões na página de facturação","type":"task","status":"done","priority":"low","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","i18n","copy"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-012","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:49:42Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-040-copy-botoes-pagina-facturacao.md","description":"Actualizar o texto dos botões na página de facturação (subscrição activa).","acceptanceCriteria":[{"checked":true,"text":"Botão portal: **Gerir Subscrição** (PT) / equivalente EN"},{"checked":true,"text":"Botão perfil: **Gerir Dados de Facturação e facturas** (PT) / equivalente EN"}],"acceptanceCriteriaRaw":"- [x] Botão portal: **Gerir Subscrição** (PT) / equivalente EN\n- [x] Botão perfil: **Gerir Dados de Facturação e facturas** (PT) / equivalente EN","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-07-31T16:49:42Z","kind":"prompt","author":"Marco Mendão","summary":"Alterar copy: Gerir Subscrição; Gerir Dados de Facturação e facturas."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"e6ab76c","repo":"coachid_app_frontend","date":"2026-07-31T16:51:37Z","author":"Marco Mendão","message":"fix country picker and billing button copy"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:49:42Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: update billing page button labels. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md":{"id":"S-013","title":"Dialog CTA quando subscrição activa sem dados de facturação","type":"story","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":502,"actualMinutes":482,"actualMs":28969000,"tags":["pagamentos","facturacao","stripe","ux","dialog"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-010","epic":"E-010","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-30T23:46:32Z","completedAt":"2026-08-03T15:57:46Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md","userStory":"Como utilizador com uma conta com **subscrição activa** mas sem dados de facturação preenchidos, quero ver um dialog de call-to-action que me leve à página de definições de facturação, para completar os dados fiscais em falta.","acceptanceCriteria":[{"checked":true,"text":"Se a conta tem **subscrição activa** e **não tem dados de facturação** (ou estão incompletos segundo as regras do produto), é mostrado um dialog CTA"},{"checked":true,"text":"O dialog explica claramente que faltam dados de facturação e tem acção primária que **redirecciona** para a página de definições de facturação da conta em questão"},{"checked":true,"text":"O dialog não aparece quando os dados de facturação já estão completos"},{"checked":true,"text":"O dialog **não** aparece durante setup/onboarding da equipa, nem enquanto a conta não tiver pelo menos uma equipa activa"},{"checked":true,"text":"Comportamento razoável de dismiss/snooze (se aplicável) sem bloquear permanentemente o uso da app, alinhado com o padrão UX existente"}],"acceptanceCriteriaRaw":"- [x] Se a conta tem **subscrição activa** e **não tem dados de facturação** (ou estão incompletos segundo as regras do produto), é mostrado um dialog CTA\n- [x] O dialog explica claramente que faltam dados de facturação e tem acção primária que **redirecciona** para a página de definições de facturação da conta em questão\n- [x] O dialog não aparece quando os dados de facturação já estão completos\n- [x] O dialog **não** aparece durante setup/onboarding da equipa, nem enquanto a conta não tiver pelo menos uma equipa activa\n- [x] Comportamento razoável de dismiss/snooze (se aplicável) sem bloquear permanentemente o uso da app, alinhado com o padrão UX existente","tasksMarkdown":"- [B-019](items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md) — Dialog de facturação aparece durante o setup da equipa\n- [B-035](items/B-035-modal-completa-faturacao-botoes-colados.md) — Modal Completa faturação — botões colados sem margem","children":[{"id":"B-019","title":"Dialog de facturação aparece durante o setup da equipa","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md"},{"id":"B-035","title":"Modal Completa faturação — botões colados sem margem","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-035-modal-completa-faturacao-botoes-colados.md"}],"promptFeedback":[{"index":"1","when":"2026-07-30T22:32:01Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic Pagamentos — dialog CTA subscrição activa sem facturação."},{"index":"2","when":"2026-07-30T23:46:32Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — implementa a E-010 (S-012/S-013/S-014)."}],"commits":[{"sha":"59a72ef","repo":"coachid_app_frontend","date":"2026-07-31T16:14:00Z","author":"Marco Mendão","message":"hide billing profile dialog until account has a team"},{"sha":"13f4ccd","repo":"coachid_app_frontend","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile page and completion cta"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:57:46Z","ended":"2026-08-03T15:57:46Z","summary":"rollup: all children done (1 kids)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md":{"id":"B-019","title":"Dialog de facturação aparece durante o setup da equipa","type":"bug","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","setup","onboarding","dialog","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-013","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T16:01:49Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md","description":"O dialog **Completa o teu perfil** (CTA de facturação incompleta com subscrição activa) aparece enquanto o utilizador está no fluxo de setup/onboarding da equipa. Só deve aparecer depois de a conta ter **pelo menos uma equipa**.","acceptanceCriteria":[{"checked":true,"text":"O dialog de facturação **não** aparece em rotas de `/setup/` ou `/onboarding/`"},{"checked":true,"text":"O dialog **não** aparece se a organização não tiver pelo menos uma equipa activa"},{"checked":true,"text":"Com subscrição activa, facturação incompleta e ≥1 equipa, o dialog continua a aparecer no app (fora de setup/onboarding e da página de perfil)"}],"acceptanceCriteriaRaw":"- [x] O dialog de facturação **não** aparece em rotas de `/setup/` ou `/onboarding/`\n- [x] O dialog **não** aparece se a organização não tiver pelo menos uma equipa activa\n- [x] Com subscrição activa, facturação incompleta e ≥1 equipa, o dialog continua a aparecer no app (fora de setup/onboarding e da página de perfil)","reproSteps":"1. Conta com subscrição activa e perfil de facturação incompleto.\n2. Entrar no setup (ou onboarding) para criar a primeira equipa — ou estar nesse fluxo sem equipa activa.\n3. Observar o dialog Completa o teu perfil.","fixCriteria":"- [x] O dialog de facturação **não** aparece em rotas de `/setup/` ou `/onboarding/`\n- [x] O dialog **não** aparece se a organização não tiver pelo menos uma equipa activa\n- [x] Com subscrição activa, facturação incompleta e ≥1 equipa, o dialog continua a aparecer no app (fora de setup/onboarding e da página de perfil)","notes":"Worktree: `worktree-1/coachid_app_frontend`. Gate: `BillingCompletionGate` / `BillingCompletionPrompt`.","promptFeedback":[{"index":"1","when":"2026-07-31T16:01:49Z","kind":"prompt","author":"Marco Mendão","summary":"Dialog Completa o teu perfil não deve aparecer no setup; só com ≥1 equipa."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"59a72ef","repo":"coachid_app_frontend","date":"2026-07-31T16:14:00Z","author":"Marco Mendão","message":"hide billing profile dialog until account has a team"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T16:01:49Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: hide billing completion dialog until account has a team. — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-035-modal-completa-faturacao-botoes-colados.md":{"id":"B-035","title":"Modal Completa faturação — botões colados sem margem","type":"bug","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":22,"actualMinutes":2,"actualMs":169000,"tags":["pagamentos","facturacao","ux","dialog"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-013","epic":"E-010","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-11T11:29:50Z","completedAt":"2026-08-11T11:32:39Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-035-modal-completa-faturacao-botoes-colados.md","description":"Na modal **Completa os dados de faturação**, os botões «Talvez mais tarde» e «Completar faturação» ficam colados um ao outro em viewports `sm+` por causa de `sm:gap-0` no `DialogFooter`.","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"1. Abrir a app com subscrição activa e dados de facturação incompletos\n2. Ver a modal «Completa os dados de faturação»\n3. Observar os botões no footer","fixCriteria":"","notes":"`BillingCompletionPrompt.tsx`: `DialogFooter className=\"gap-2 sm:gap-0\"` — o `sm:gap-0` anula o gap do componente base.","promptFeedback":[{"index":"1","when":"2026-08-11T11:29:50Z","kind":"prompt","author":"Marco Mendão","summary":"Modal Completa faturação: botões colados — dar margem entre eles"},{"index":"2","when":"2026-08-11T11:32:39Z","kind":"feedback","author":"Marco Mendão","summary":"Removido sm:gap-0; DialogFooter usa gap-2 por defeito"}],"commits":[{"sha":"01f4a04","repo":"coachid_app_frontend","date":"2026-08-11T15:00:10Z","author":"Marco Mendão","message":"fix billing completion modal button spacing"},{"sha":"a976730","repo":"coachid_app_frontend","date":"2026-08-11T15:00:11Z","author":"Marco Mendão","message":"fix billing completion modal button spacing"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-11T11:29:50Z","ended":"2026-08-11T11:32:39Z","summary":"Fixed button gap on Completa faturação modal"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md":{"id":"S-014","title":"Listagem de facturas Stripe na página de facturação","type":"story","status":"done","priority":"medium","size":"S","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","stripe","invoices"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-010","epic":"E-010","created":"2026-07-30","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-30T23:46:32Z","completedAt":"2026-08-03T15:57:46Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md","userStory":"Como titular da conta, quero ver na página de definições de facturação a lista das minhas facturas (por agora as facturas do Stripe), para consultar histórico e descarregar comprovativos.","acceptanceCriteria":[{"checked":true,"text":"Na página de facturação da conta aparece uma secção/lista com **todas as facturas do utilizador/conta**"},{"checked":true,"text":"Nesta fase a fonte de verdade é o **Stripe** (invoices da customer/subscription associada)"},{"checked":true,"text":"Cada item mostra informação útil (data, montante, estado, link/PDF Stripe quando disponível)"},{"checked":true,"text":"Estado vazio tratado (sem facturas ainda) e erros de carregamento com feedback claro"},{"checked":true,"text":"Lista está no contexto da **conta** seleccionada (pessoal vs organização)"}],"acceptanceCriteriaRaw":"- [x] Na página de facturação da conta aparece uma secção/lista com **todas as facturas do utilizador/conta**\n- [x] Nesta fase a fonte de verdade é o **Stripe** (invoices da customer/subscription associada)\n- [x] Cada item mostra informação útil (data, montante, estado, link/PDF Stripe quando disponível)\n- [x] Estado vazio tratado (sem facturas ainda) e erros de carregamento com feedback claro\n- [x] Lista está no contexto da **conta** seleccionada (pessoal vs organização)","tasksMarkdown":"- [T-034](items/T-034-lista-facturas-paginada-5-por-pagina.md) — Lista de facturas paginada (máx. 5 por página)","children":[{"id":"T-034","title":"Lista de facturas paginada (máx. 5 por página)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/items/T-034-lista-facturas-paginada-5-por-pagina.md"}],"promptFeedback":[{"index":"1","when":"2026-07-30T22:32:01Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic Pagamentos — listagem facturas Stripe na página de facturação."},{"index":"2","when":"2026-07-30T23:46:32Z","kind":"prompt","author":"Marco Mendão","summary":"/start-work — implementa a E-010 (S-012/S-013/S-014)."}],"commits":[{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"},{"sha":"ad0d17e","repo":"coachid_app_api","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile and stripe invoices api"},{"sha":"13f4ccd","repo":"coachid_app_frontend","date":"2026-07-31T06:40:45Z","author":"Marco Mendão","message":"add billing profile page and completion cta"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:57:46Z","ended":"2026-08-03T15:57:46Z","summary":"rollup: all children done (1 kids)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/items/T-034-lista-facturas-paginada-5-por-pagina.md":{"id":"T-034","title":"Lista de facturas paginada (máx. 5 por página)","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["pagamentos","facturacao","invoices","pagination"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-014","epic":"E-010","created":"2026-07-31","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-07-31T07:26:46Z","completedAt":"2026-08-03T15:57:14Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/items/T-034-lista-facturas-paginada-5-por-pagina.md","description":"Na página de dados de facturação, a listagem de facturas Stripe deve ser paginada com no máximo **5** facturas por página.","acceptanceCriteria":[{"checked":true,"text":"A lista mostra no máximo 5 facturas por página"},{"checked":true,"text":"Há controlos para navegar entre páginas quando há mais de 5 facturas"},{"checked":true,"text":"Estados vazio e erro continuam a funcionar"}],"acceptanceCriteriaRaw":"- [x] A lista mostra no máximo 5 facturas por página\n- [x] Há controlos para navegar entre páginas quando há mais de 5 facturas\n- [x] Estados vazio e erro continuam a funcionar","reproSteps":"","fixCriteria":"","notes":"Worktree: `worktree-1/coachid_app_frontend`.","promptFeedback":[{"index":"1","when":"2026-07-31T07:26:46Z","kind":"prompt","author":"Marco Mendão","summary":"A lista de facturas deve ser paginada máximo 5 por página."},{"index":"close","when":"2026-08-03T15:57:14Z","kind":"feedback","author":"Marco Mendão","summary":"Closed stale in_progress; AC already done."}],"commits":[{"sha":"398e4f5","repo":"coachid_app_frontend","date":"2026-07-31T15:59:06Z","author":"Marco Mendão","message":"improve billing form and stripe admin customer link"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-07-31T07:26:46Z","ended":"2026-08-01T12:00:00Z","summary":"In progress: paginate billing invoices list (5/page). — auto-closed: idle cap (next-day 12:00 UTC)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/epic.md":{"id":"E-011","title":"Backup do produto","type":"epic","status":"done","priority":"high","size":"—","points":16,"estimateMinutes":585,"actualMinutes":486,"actualMs":29192000,"tags":["ops","backup","mongo","s3","infra"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:40:23Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/epic.md","goal":"Garantir backups diários (e manuais) da base de dados MongoDB do CoachID, empacotados em ZIP e armazenados no bucket S3 `coachid-backups`.","scope":"- Dump MongoDB → ZIP → upload para `coachid-backups`\n- Job automático todas as noites às **02:00**\n- CLI via NPM para backup manual, com prompts `inquirer` (host, username, password; defaults a partir das env vars)","outOfScope":"- Restore UI / restore automático\n- Backup de ficheiros de media (S3 de produto) — só dump da base Mongo nesta fase\n- Retenção/lifecycle policies avançadas (pode ser follow-up)","successMetrics":"- Backup nocturno a aparecer no bucket todos os dias\n- Operador consegue disparar backup manual via `npm` com confirmação de credenciais","storiesMarkdown":"- [S-015](stories/S-015-backup-automatico-diario-mongo-s3/story.md) — Backup automático diário Mongo → S3 (02:00)\n- [S-016](stories/S-016-cli-backup-manual-inquirer/story.md) — CLI NPM para backup manual com inquirer","children":[{"id":"S-015","title":"Backup automático diário Mongo → S3 (02:00)","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md"},{"id":"S-016","title":"CLI NPM para backup manual com inquirer","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md"},{"id":"T-064","title":"Script para apagar wellness/RPE legacy do Mongo","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md"}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"},{"sha":"51c6bc8","repo":"coachid_app_api","date":"2026-08-11T00:47:55+01:00","author":"Marco Mendão","message":"add legacy mongo purge script and backup zip label"},{"sha":"220f79a","repo":"coachid-taskmark","date":"2026-08-11T00:47:56+01:00","author":"Marco Mendão","message":"update taskmark board for legacy purge script"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:40:23Z","ended":"2026-08-03T15:44:22Z","summary":"rollup: E-011 delivered (shared-batch on T-042..T-045)"},{"session":"2","actor":"Marco Mendão","started":"2026-08-11T16:08:09Z","ended":"2026-08-11T16:08:09Z","summary":"rollup: all stories/leaves done (S-015, S-016, T-064)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md":{"id":"T-064","title":"Script para apagar wellness/RPE legacy do Mongo","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":50,"actualMinutes":2,"actualMs":153000,"tags":["ops","mongo","cleanup","wellness","rpe","backup"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-011","epic":"E-011","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T23:36:00Z","completedAt":"2026-08-10T23:47:21Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md","description":"CLI one-shot na API para limpar dados da app antiga que incham o backup Mongo:\n\n- `wellnesses` com schema legado (`stats` como array / sem `player` no topo)\n- `rpes` ligados a `trainings`/`games` (sessões legacy)\n- promover `wellnesses-v2` → `wellnesses` (schema da app nova)\n- dropar collection `notifications` (entidade legacy não usada)\n- apagar exercícios legacy (icons/playersArray SVG; manter schema Nest)\n\nDry-run por defeito; execução exige confirmação explícita.","acceptanceCriteria":[{"checked":true,"text":"`npm run purge:legacy-wellness-rpe` (ou `--dry-run`) reporta contagens sem apagar"},{"checked":true,"text":"`--execute` apaga só wellness legacy + RPEs com `referenceId` em trainings/games"},{"checked":true,"text":"Opção para promover `wellnesses-v2` para `wellnesses` e dropar a collection v2"},{"checked":true,"text":"Prompts inquirer + confirmação do nome da DB antes de executar"},{"checked":true,"text":"Dropar `notifications` (com `--no-drop-notifications` para skip)"},{"checked":true,"text":"Apagar exercícios legacy (com `--no-purge-legacy-exercises` para skip)"}],"acceptanceCriteriaRaw":"- [x] `npm run purge:legacy-wellness-rpe` (ou `--dry-run`) reporta contagens sem apagar\n- [x] `--execute` apaga só wellness legacy + RPEs com `referenceId` em trainings/games\n- [x] Opção para promover `wellnesses-v2` para `wellnesses` e dropar a collection v2\n- [x] Prompts inquirer + confirmação do nome da DB antes de executar\n- [x] Dropar `notifications` (com `--no-drop-notifications` para skip)\n- [x] Apagar exercícios legacy (com `--no-purge-legacy-exercises` para skip)","reproSteps":"","fixCriteria":"","notes":"Análise no dump prod (~2.3 GB): `wellnesses` 100% schema antigo (~74k); `wellnesses-v2` ~1.8k (2026); `rpes` ~99.9% pré-2026. Após dropar notifications (~464 MB), o maior peso restante costuma ser `exercises` (~60%).","promptFeedback":[{"index":"1","when":"2026-08-10T23:37:37Z","kind":"prompt","author":"Marco Mendão","summary":"Criar script para apagar wellness/RPE legacy do Mongo (dry-run + execute)."},{"index":"2","when":"2026-08-10T23:38:32Z","kind":"feedback","author":"Marco Mendão","summary":"Script adicionado em coachid_app_api (npm run purge:legacy-wellness-rpe)."},{"index":"3","when":"2026-08-10T23:45:04Z","kind":"prompt","author":"Marco Mendão","summary":"Atualizar script para remover também a collection notifications."},{"index":"4","when":"2026-08-10T23:45:05Z","kind":"feedback","author":"Marco Mendão","summary":"Script atualizado para dropar notifications."},{"index":"5","when":"2026-08-10T23:47:21Z","kind":"prompt","author":"Marco Mendão","summary":"Atualizar script para apagar também exercícios legacy."},{"index":"6","when":"2026-08-10T23:47:21Z","kind":"feedback","author":"Marco Mendão","summary":"Script atualizado para purge de exercises legacy."}],"commits":[{"sha":"51c6bc8","repo":"coachid_app_api","date":"2026-08-11T00:47:55+01:00","author":"Marco Mendão","message":"add legacy mongo purge script and backup zip label"},{"sha":"220f79a","repo":"coachid-taskmark","date":"2026-08-11T00:47:56+01:00","author":"Marco Mendão","message":"update taskmark board for legacy purge script"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T23:36:00Z","ended":"2026-08-10T23:38:32Z","summary":"Added purge:legacy-wellness-rpe CLI (dry-run default, promote wellnesses-v2, delete legacy wellness + RPEs linked to trainings/games)."},{"session":"2","actor":"Marco Mendão","started":"2026-08-10T23:45:04Z","ended":"2026-08-10T23:45:05Z","summary":"Extended purge to drop unused notifications collection (~464MB no dump prod)."},{"session":"3","actor":"Marco Mendão","started":"2026-08-10T23:47:21Z","ended":"2026-08-10T23:47:21Z","summary":"Extended purge to delete legacy exercises (icons/playersArray)."}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md":{"id":"S-015","title":"Backup automático diário Mongo → S3 (02:00)","type":"story","status":"done","priority":"high","size":"L","points":10,"estimateMinutes":515,"actualMinutes":482,"actualMs":28952000,"tags":["ops","backup","mongo","s3","cron"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-011","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:40:23Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md","userStory":"Como operador do produto, quero que todas as noites às **02:00** seja criado um ZIP com o backup da base MongoDB e enviado para o bucket S3 `coachid-backups`, para ter um ponto de recuperação diário sem intervenção manual.","acceptanceCriteria":[{"checked":true,"text":"Todas as noites às **02:00** (timezone definida e documentada) corre um job de backup"},{"checked":true,"text":"O job faz dump da MongoDB, empacota num **ZIP** e faz upload para o bucket **`coachid-backups`**"},{"checked":true,"text":"O objecto no S3 tem nome/chave identificável (ex. data/hora + ambiente)"},{"checked":true,"text":"Falhas (dump, zip ou upload) são logadas de forma clara"},{"checked":true,"text":"Credenciais e destino usam variáveis de ambiente do sistema (reutilizáveis pelo CLI)"}],"acceptanceCriteriaRaw":"- [x] Todas as noites às **02:00** (timezone definida e documentada) corre um job de backup\n- [x] O job faz dump da MongoDB, empacota num **ZIP** e faz upload para o bucket **`coachid-backups`**\n- [x] O objecto no S3 tem nome/chave identificável (ex. data/hora + ambiente)\n- [x] Falhas (dump, zip ou upload) são logadas de forma clara\n- [x] Credenciais e destino usam variáveis de ambiente do sistema (reutilizáveis pelo CLI)","tasksMarkdown":"- [T-042](items/T-042-pipeline-mongodump-zip-upload-s3.md) — Pipeline mongodump → ZIP → upload S3\n- [T-043](items/T-043-agendar-backup-diario-02h.md) — Agendar backup diário às 02:00\n- [T-063](items/T-063-backup-filename-app-base-url.md) — Nome do ZIP de backup a partir de APP_BASE_URL","children":[{"id":"T-042","title":"Pipeline mongodump → ZIP → upload S3","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-042-pipeline-mongodump-zip-upload-s3.md"},{"id":"T-043","title":"Agendar backup diário às 02:00","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-043-agendar-backup-diario-02h.md"},{"id":"T-063","title":"Nome do ZIP de backup a partir de APP_BASE_URL","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-063-backup-filename-app-base-url.md"}],"promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — backup diário Mongo ZIP → coachid-backups + CLI npm/inquirer."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:44:22Z","ended":"2026-08-03T15:44:22Z","summary":"rollup: all children done (shared-batch on tasks)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-042-pipeline-mongodump-zip-upload-s3.md":{"id":"T-042","title":"Pipeline mongodump → ZIP → upload S3","type":"task","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":25,"actualMinutes":1,"actualMs":108000,"tags":["ops","backup","mongo","s3"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-015","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:40:23Z","completedAt":"2026-08-03T15:42:11Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-042-pipeline-mongodump-zip-upload-s3.md","description":"Implementar o serviço/core reutilizável que: (1) corre `mongodump` (ou equivalente) contra a Mongo configurada; (2) empacota o resultado num ficheiro **ZIP**; (3) faz upload para o bucket S3 **`coachid-backups`**. Deve aceitar parâmetros de ligação (host, user, password, db) para ser usado pelo job agendado e pelo CLI.","acceptanceCriteria":[{"checked":true,"text":"Dado host/user/password (e db se aplicável), produz um dump da Mongo"},{"checked":true,"text":"O dump é empacotado num ZIP com nome datado/identificável"},{"checked":true,"text":"O ZIP é enviado para o bucket `coachid-backups` (credenciais AWS via env existentes ou dedicadas)"},{"checked":true,"text":"Erros de dump/zip/upload falham de forma explícita (exit code / exception + log)"},{"checked":true,"text":"Artefactos temporários locais são limpos após upload (sucesso ou falha controlada)"}],"acceptanceCriteriaRaw":"- [x] Dado host/user/password (e db se aplicável), produz um dump da Mongo\n- [x] O dump é empacotado num ZIP com nome datado/identificável\n- [x] O ZIP é enviado para o bucket `coachid-backups` (credenciais AWS via env existentes ou dedicadas)\n- [x] Erros de dump/zip/upload falham de forma explícita (exit code / exception + log)\n- [x] Artefactos temporários locais são limpos após upload (sucesso ou falha controlada)","reproSteps":"","fixCriteria":"","notes":"Preferir reutilizar o stack S3 já presente na API (`@aws-sdk/client-s3`). Destino fixo do produto: bucket `coachid-backups`.","promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"Pipeline dump Mongo → zip → coachid-backups."},{"index":"2","when":"2026-08-03T15:44:22Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of E-011 backup epic."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:40:23Z","ended":"2026-08-03T15:42:11Z","summary":"shared-batch: pipeline mongodump zip S3 (1 of 3min by points)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-043-agendar-backup-diario-02h.md":{"id":"T-043","title":"Agendar backup diário às 02:00","type":"task","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":10,"actualMinutes":0,"actualMs":44000,"tags":["ops","backup","cron","schedule"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-015","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:42:11Z","completedAt":"2026-08-03T15:42:55Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-043-agendar-backup-diario-02h.md","description":"Agendar o pipeline de backup (T-042) para correr **todas as noites às 02:00**. Usar o mecanismo de scheduling já disponível na API (`@nestjs/schedule`) ou cron do host — documentar a timezone escolhida.","acceptanceCriteria":[{"checked":true,"text":"Job corre diariamente às **02:00** (timezone documentada)"},{"checked":true,"text":"Invoca o mesmo pipeline de dump → ZIP → S3 do T-042"},{"checked":true,"text":"Usa as variáveis de ambiente do sistema para a ligação Mongo (sem prompts)"},{"checked":true,"text":"Overlap / falha anterior não deixa o processo num estado silencioso (log + métrica/alerta se já existir padrão)"}],"acceptanceCriteriaRaw":"- [x] Job corre diariamente às **02:00** (timezone documentada)\n- [x] Invoca o mesmo pipeline de dump → ZIP → S3 do T-042\n- [x] Usa as variáveis de ambiente do sistema para a ligação Mongo (sem prompts)\n- [x] Overlap / falha anterior não deixa o processo num estado silencioso (log + métrica/alerta se já existir padrão)","reproSteps":"","fixCriteria":"","notes":"No modo automático **não** usar inquirer — só env vars.","promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"Job nocturno 02:00 para backup Mongo."},{"index":"2","when":"2026-08-03T15:44:22Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of E-011 backup epic."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:42:11Z","ended":"2026-08-03T15:42:55Z","summary":"shared-batch: cron 02:00 Europe/Lisbon (0 of 3min by points)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-063-backup-filename-app-base-url.md":{"id":"T-063","title":"Nome do ZIP de backup a partir de APP_BASE_URL","type":"task","status":"done","priority":"medium","size":"M","points":3,"estimateMinutes":480,"actualMinutes":480,"actualMs":28800000,"tags":["ops","backup","mongo","s3"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-015","epic":"E-011","created":"2026-08-11","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-10T23:23:44Z","completedAt":"2026-08-11T16:08:09Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-063-backup-filename-app-base-url.md","description":"O host Mongo em Docker é tipicamente o mesmo (`mongodb`) em todos os ambientes, por isso não serve para distinguir backups no S3. Usar o hostname de `APP_BASE_URL` no nome do ZIP (ex. `mongo-backup-app.coachidapp.com-….zip`) e fazer upload em stream para evitar OOM com dumps grandes.","acceptanceCriteria":[{"checked":true,"text":"No cron, o nome do ZIP / S3 key inclui um label derivado de `APP_BASE_URL` (hostname), não do host Mongo Docker"},{"checked":true,"text":"No CLI manual, o label vem do host que o utilizador introduz no prompt (não `APP_BASE_URL`)"},{"checked":true,"text":"Upload S3 faz stream do ficheiro (não `readFile` completo para memória)"},{"checked":true,"text":"`.env.example` documenta a diferença cron vs CLI"}],"acceptanceCriteriaRaw":"- [x] No cron, o nome do ZIP / S3 key inclui um label derivado de `APP_BASE_URL` (hostname), não do host Mongo Docker\n- [x] No CLI manual, o label vem do host que o utilizador introduz no prompt (não `APP_BASE_URL`)\n- [x] Upload S3 faz stream do ficheiro (não `readFile` completo para memória)\n- [x] `.env.example` documenta a diferença cron vs CLI","reproSteps":"","fixCriteria":"","notes":"Relacionado com T-042. Em falta de label/`APP_BASE_URL` o fallback é `unknown-app`.","promptFeedback":[{"index":"1","when":"2026-08-10T23:23:44Z","kind":"prompt","author":"Marco Mendão","summary":"Host Mongo é sempre local; usar APP_BASE_URL no nome do backup."},{"index":"2","when":"2026-08-10T23:28:06Z","kind":"prompt","author":"Marco Mendão","summary":"No CLI, usar sempre o host fornecido pelo utilizador em vez de APP_BASE_URL."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-10T23:23:44Z","ended":"2026-08-11T12:00:00Z","summary":"In progress: label ZIP via APP_BASE_URL + stream S3 upload · auto-closed: idle cap (next-day 12:00 UTC); backup ZIP label from APP_BASE_URL"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md":{"id":"S-016","title":"CLI NPM para backup manual com inquirer","type":"story","status":"done","priority":"high","size":"M","points":4,"estimateMinutes":20,"actualMinutes":1,"actualMs":87000,"tags":["ops","backup","cli","inquirer","npm"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"E-011","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:40:23Z","completedAt":"2026-08-03T15:44:22Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md","userStory":"Como operador, quero executar um comando NPM que dispare o mesmo pipeline de backup, pedindo-me sempre o **host**, **username** e **password** da Mongo (com defaults das env vars via [inquirer](https://www.npmjs.com/package/inquirer)), para fazer backups manuais com confirmação explícita do destino.","acceptanceCriteria":[{"checked":true,"text":"Existe um script NPM (ex. `npm run backup:mongo`) que corre o backup manualmente"},{"checked":true,"text":"O CLI usa **`inquirer`** e **pergunta sempre** host, username e password"},{"checked":true,"text":"Os valores por defeito dos prompts vêm das variáveis de ambiente do sistema"},{"checked":true,"text":"Após confirmação, executa o mesmo fluxo dump → ZIP → S3 `coachid-backups`"},{"checked":true,"text":"Uso documentado (comando, env vars relevantes, bucket)"}],"acceptanceCriteriaRaw":"- [x] Existe um script NPM (ex. `npm run backup:mongo`) que corre o backup manualmente\n- [x] O CLI usa **`inquirer`** e **pergunta sempre** host, username e password\n- [x] Os valores por defeito dos prompts vêm das variáveis de ambiente do sistema\n- [x] Após confirmação, executa o mesmo fluxo dump → ZIP → S3 `coachid-backups`\n- [x] Uso documentado (comando, env vars relevantes, bucket)","tasksMarkdown":"- [T-044](items/T-044-cli-npm-inquirer-backup-mongo.md) — CLI npm + inquirer (host, user, password)\n- [T-045](items/T-045-documentar-backup-env-uso.md) — Documentar env vars e uso do backup","children":[{"id":"T-044","title":"CLI npm + inquirer (host, user, password)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-044-cli-npm-inquirer-backup-mongo.md"},{"id":"T-045","title":"Documentar env vars e uso do backup","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-045-documentar-backup-env-uso.md"}],"promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"/create-task — CLI npm com inquirer para backup manual; defaults das env."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:44:22Z","ended":"2026-08-03T15:44:22Z","summary":"rollup: all children done (shared-batch on tasks)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-044-cli-npm-inquirer-backup-mongo.md":{"id":"T-044","title":"CLI npm + inquirer (host, user, password)","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":15,"actualMinutes":1,"actualMs":65000,"tags":["ops","backup","cli","inquirer","npm"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-016","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:42:55Z","completedAt":"2026-08-03T15:44:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-044-cli-npm-inquirer-backup-mongo.md","description":"Expor um comando via **NPM** (ex. `npm run backup:mongo`) que dispara o pipeline de backup. Usar a lib [`inquirer`](https://www.npmjs.com/package/inquirer). Por defeito pré-preencher com as variáveis de ambiente do sistema, mas **perguntar sempre** ao utilizador o **host**, **username** e **password** do destino Mongo do backup.","acceptanceCriteria":[{"checked":true,"text":"Script NPM documentado e funcional (ex. `backup:mongo`)"},{"checked":true,"text":"Dependência `inquirer` adicionada onde o CLI vive"},{"checked":true,"text":"Prompts obrigatórios: host, username, password (password mascarada)"},{"checked":true,"text":"Defaults dos prompts = valores das env vars existentes (quando presentes)"},{"checked":true,"text":"Após respostas, corre o pipeline partilhado (T-042) com essas credenciais"},{"checked":true,"text":"Exit code ≠ 0 em caso de falha"}],"acceptanceCriteriaRaw":"- [x] Script NPM documentado e funcional (ex. `backup:mongo`)\n- [x] Dependência `inquirer` adicionada onde o CLI vive\n- [x] Prompts obrigatórios: host, username, password (password mascarada)\n- [x] Defaults dos prompts = valores das env vars existentes (quando presentes)\n- [x] Após respostas, corre o pipeline partilhado (T-042) com essas credenciais\n- [x] Exit code ≠ 0 em caso de falha","reproSteps":"","fixCriteria":"","notes":"Worktree alvo provável: `coachid_app_api` (já tem Mongo + S3 + `@nestjs/schedule`).","promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"CLI npm com inquirer; defaults env; perguntar sempre host/user/password."},{"index":"2","when":"2026-08-03T15:44:22Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of E-011 backup epic."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:42:55Z","ended":"2026-08-03T15:44:00Z","summary":"shared-batch: npm backup:mongo + inquirer (1 of 3min by points)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-045-documentar-backup-env-uso.md":{"id":"T-045","title":"Documentar env vars e uso do backup","type":"task","status":"done","priority":"medium","size":"XS","points":1,"estimateMinutes":5,"actualMinutes":0,"actualMs":22000,"tags":["ops","backup","docs"],"owner":"Marco Mendão","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-016","epic":"E-011","created":"2026-08-03","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-03T15:44:00Z","completedAt":"2026-08-03T15:44:22Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-045-documentar-backup-env-uso.md","description":"Documentar como correr o backup automático vs manual: variáveis de ambiente (Mongo + AWS/S3), bucket `coachid-backups`, horário 02:00, e o comando NPM com inquirer.","acceptanceCriteria":[{"checked":true,"text":"`.env.example` (ou equivalente) lista as vars necessárias ao backup"},{"checked":true,"text":"README / secção ops descreve: job 02:00, bucket, e `npm run backup:mongo` (ou nome final)"},{"checked":true,"text":"Nota sobre timezone do cron e permissões S3 no bucket `coachid-backups`"}],"acceptanceCriteriaRaw":"- [x] `.env.example` (ou equivalente) lista as vars necessárias ao backup\n- [x] README / secção ops descreve: job 02:00, bucket, e `npm run backup:mongo` (ou nome final)\n- [x] Nota sobre timezone do cron e permissões S3 no bucket `coachid-backups`","reproSteps":"","fixCriteria":"","notes":"Manter curto e operacional — não um runbook longo.","promptFeedback":[{"index":"1","when":"2026-08-03T15:33:48Z","kind":"prompt","author":"Marco Mendão","summary":"Documentar uso e env do mecanismo de backup."},{"index":"2","when":"2026-08-03T15:44:22Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented as part of E-011 backup epic."}],"commits":[{"sha":"bcfee96","repo":"coachid_app_api","date":"2026-08-03T16:49:46+01:00","author":"Marco Mendão","message":"add mongo backup to s3 and cli"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-03T15:44:00Z","ended":"2026-08-03T15:44:22Z","summary":"shared-batch: document env and README (0 of 3min by points)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/epic.md":{"id":"E-012","title":"Auth UI — login, registo e convites de organização","type":"epic","status":"done","priority":"high","size":"—","points":64,"estimateMinutes":2160,"actualMinutes":121,"actualMs":7297335,"tags":["auth","auth0","login","signup","convites","sendgrid","ui","shadcn","organizacoes"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"","epic":"","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T17:07:19Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/epic.md","goal":"Refazer as interfaces de **login** e **registo** do produto com blocos shadcn ([login-02](https://ui.shadcn.com/blocks/login#login-02), [signup-02](https://ui.shadcn.com/blocks/signup#signup-02)), mantendo **Auth0 por detrás** para identidade. Completar o fluxo de **convite para organização** (email SendGrid) que ficou em falta após a saída das Auth0 Organizations (S-017): registo por convite, login + confirmação, e tratamento de utilizador já autenticado (incluindo erro se o convite não pertencer à sessão).","scope":"- Nova UI de login (layout dois painéis / cover image — login-02)\n- Nova UI de registo normal (layout dois painéis — signup-02)\n- Registo **por convite** (email readonly + contexto da organização)\n- Template SendGrid de convite + envio na criação/reenvio de invite\n- Página de confirmação para aceitar convite (utilizador existente / já logado)\n- Página de erro quando o utilizador logado **não** é o convidado\n- Redirect pós-aceitação para o lineup da organização","outOfScope":"- Substituir Auth0 por outro IdP\n- Alterar o modelo de membership já existente (apenas ligar email + UX de aceitação)\n- Redesign completo do Universal Login alojado no Auth0 (a app usa UI própria que chama Auth0)","successMetrics":"- Login e registo normal usáveis com a nova UI e Auth0\n- Convite por email chega ao destinatário e abre o fluxo correcto (registo vs login+confirmação vs confirmação directa)\n- Utilizador errado logado vê erro claro com opções de trocar de conta ou ir ao início\n- Após aceitar, o utilizador aterra no lineup da organização convidada","storiesMarkdown":"- [S-018](stories/S-018-ui-login-shadcn-login-02/story.md) — Nova UI de login (shadcn login-02) com Auth0\n- [S-019](stories/S-019-ui-registo-normal-shadcn-signup-02/story.md) — Nova UI de registo normal (shadcn signup-02) com Auth0\n- [S-020](stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md) — Fluxo de convite para organização (email, registo, login e confirmação)","children":[{"id":"S-018","title":"Nova UI de login (shadcn login-02) com Auth0","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md"},{"id":"S-019","title":"Nova UI de registo normal (shadcn signup-02) com Auth0","type":"story","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md"},{"id":"S-020","title":"Fluxo de convite para organização (email, registo, login e confirmação)","type":"story","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md"}],"commits":[{"sha":"6f5b71a","repo":"coachid_app_frontend","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add auth login signup forgot password and invites"},{"sha":"cde87fd","repo":"coachid_app_api","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add org invite email and invitation token"},{"sha":"6192d7a","repo":"coachid-taskmark","date":"2026-08-12T17:09:30Z","author":"Marco Mendão","message":"sync taskmark board for auth ui and T-078"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:46:38Z","summary":"shared-batch parent rollup (0 min; effort on tasks)"},{"session":"2","actor":"Marco Mendão","started":"2026-08-12T17:07:19Z","ended":"2026-08-12T17:07:19Z","summary":"shared-batch parent rollup (0 min; T-078 forgot-password)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md":{"id":"S-018","title":"Nova UI de login (shadcn login-02) com Auth0","type":"story","status":"done","priority":"high","size":"XL","points":21,"estimateMinutes":625,"actualMinutes":32,"actualMs":1957934,"tags":["auth","login","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-012","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T17:12:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md","userStory":"Como utilizador, quero uma página de login moderna (layout card + imagem no padrão shadcn [login-04](https://ui.shadcn.com/blocks/login#login-04)), para autenticar-me na CoachID sem mudar o facto de a identidade continuar a ser gerida pelo Auth0.","acceptanceCriteria":[{"checked":true,"text":"Existe uma página/rota de login com o layout **login-04** (card centrado; formulário + cover image)"},{"checked":true,"text":"A marca CoachID aparece no ecrã de login (em vez do placeholder Acme)"},{"checked":true,"text":"O formulário de login autentica via **Auth0** (sem Auth0 Organizations UI para este ecrã)"},{"checked":true,"text":"Erros de credenciais / Auth0 são mostrados de forma clara no formulário"},{"checked":true,"text":"Após login com sucesso, o utilizador segue o fluxo actual da app (redirect pós-auth)"},{"checked":true,"text":"i18n PT/EN alinhado ao resto do produto"},{"checked":true,"text":"Responsivo (mobile: formulário; desktop: card com cover)"},{"checked":true,"text":"Recuperar password a partir do login (Auth0 change_password)"}],"acceptanceCriteriaRaw":"- [x] Existe uma página/rota de login com o layout **login-04** (card centrado; formulário + cover image)\n- [x] A marca CoachID aparece no ecrã de login (em vez do placeholder Acme)\n- [x] O formulário de login autentica via **Auth0** (sem Auth0 Organizations UI para este ecrã)\n- [x] Erros de credenciais / Auth0 são mostrados de forma clara no formulário\n- [x] Após login com sucesso, o utilizador segue o fluxo actual da app (redirect pós-auth)\n- [x] i18n PT/EN alinhado ao resto do produto\n- [x] Responsivo (mobile: formulário; desktop: card com cover)\n- [x] Recuperar password a partir do login (Auth0 change_password)","tasksMarkdown":"- [T-067](items/T-067-layout-pagina-login-shadcn-login-02.md) — Layout da página de login (shadcn login-02)\n- [T-068](items/T-068-ligar-formulario-login-auth0.md) — Ligar formulário de login ao Auth0\n- [T-078](items/T-078-recuperar-password-no-login.md) — Recuperar password no login (Auth0 change_password)\n- [T-079](items/T-079-adaptar-login-registo-login-04.md) — Adaptar login e registo ao layout shadcn login-04\n- [B-038](items/B-038-registo-redirect-auth0-login-em-vez-wizard.md) — Registo redirecciona para login Auth0 em vez do wizard\n- [B-039](items/B-039-confirmacao-logout-nativa.md) — Confirmação de logout nativa (sem página Auth0)\n- [B-040](items/B-040-nunca-usar-logout-auth0.md) — Nunca usar logout Auth0 (só sessão local)\n- [T-081](items/T-081-login-signup-button-spinners.md) — Login e registo — loading com spinner nos botões\n- [T-082](items/T-082-logout-sem-cover-imagem.md) — Logout — confirmação a página inteira sem cover\n- [T-083](items/T-083-auth-logo-light-cid-azul.md) — Auth light — logo cid_azul nas páginas login/logout/registo","children":[{"id":"B-038","title":"Registo redirecciona para login Auth0 em vez do wizard","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-038-registo-redirect-auth0-login-em-vez-wizard.md"},{"id":"B-039","title":"Confirmação de logout nativa (sem página Auth0)","type":"bug","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-039-confirmacao-logout-nativa.md"},{"id":"B-040","title":"Nunca usar logout Auth0 (só sessão local)","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-040-nunca-usar-logout-auth0.md"},{"id":"T-067","title":"Layout da página de login (shadcn login-02)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-067-layout-pagina-login-shadcn-login-02.md"},{"id":"T-068","title":"Ligar formulário de login ao Auth0","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-068-ligar-formulario-login-auth0.md"},{"id":"T-078","title":"Recuperar password no login (Auth0 change_password)","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-078-recuperar-password-no-login.md"},{"id":"T-079","title":"Adaptar login e registo ao layout shadcn login-04","type":"task","status":"done","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-079-adaptar-login-registo-login-04.md"},{"id":"T-081","title":"Login e registo — loading com spinner nos botões","type":"task","status":"in_progress","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-081-login-signup-button-spinners.md"},{"id":"T-082","title":"Logout — confirmação a página inteira sem cover","type":"task","status":"in_progress","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-082-logout-sem-cover-imagem.md"},{"id":"T-083","title":"Auth light — logo cid_azul nas páginas login/logout/registo","type":"task","status":"done","priority":"low","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-083-auth-logo-light-cid-azul.md"}],"promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic — UI login/registo shadcn + fluxo convite org (SendGrid, registo por convite, confirmação, erro utilizador errado)."}],"commits":[{"sha":"6f5b71a","repo":"coachid_app_frontend","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add auth login signup forgot password and invites"},{"sha":"cde87fd","repo":"coachid_app_api","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add org invite email and invitation token"},{"sha":"6192d7a","repo":"coachid-taskmark","date":"2026-08-12T17:09:30Z","author":"Marco Mendão","message":"sync taskmark board for auth ui and T-078"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:46:38Z","summary":"shared-batch parent rollup (0 min; effort on tasks)"},{"session":"2","actor":"Marco Mendão","started":"2026-08-12T17:07:19Z","ended":"2026-08-12T17:07:19Z","summary":"shared-batch parent rollup (0 min; T-078 forgot-password)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-038-registo-redirect-auth0-login-em-vez-wizard.md":{"id":"B-038","title":"Registo redirecciona para login Auth0 em vez do wizard","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":180000,"tags":["auth","signup","auth0","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:35:00Z","completedAt":"2026-08-12T17:38:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-038-registo-redirect-auth0-login-em-vez-wizard.md","description":"Após submeter o formulário de registo da app, o utilizador é enviado para o Universal Login do Auth0 em vez de ficar autenticado e entrar no wizard de inicialização. A partir de agora nunca se deve mostrar o formulário de login Auth0 — usar sempre `/login`.","acceptanceCriteria":[{"checked":true,"text":"Client redirects usam `/login` (não `/auth/login`)"},{"checked":true,"text":"Pós-registo: sessão válida e redirect para onboarding account"},{"checked":true,"text":"AuthSessionGuard não manda para Universal Login"},{"checked":true,"text":"Middleware reescreve `/auth/login` → `/login`"}],"acceptanceCriteriaRaw":"- [x] Client redirects usam `/login` (não `/auth/login`)\n- [x] Pós-registo: sessão válida e redirect para onboarding account\n- [x] AuthSessionGuard não manda para Universal Login\n- [x] Middleware reescreve `/auth/login` → `/login`","reproSteps":"","fixCriteria":"- [x] Client redirects usam `/login` (não `/auth/login`)\n- [x] Pós-registo: sessão válida e redirect para onboarding account\n- [x] AuthSessionGuard não manda para Universal Login\n- [x] Middleware reescreve `/auth/login` → `/login`","notes":"Parent: [S-018](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:35:00Z","kind":"prompt","author":"Marco Mendão","summary":"Registo avança para Auth0 UL; esperado wizard autenticado"},{"index":"2","when":"2026-08-12T17:38:00Z","kind":"feedback","author":"Marco Mendão","summary":"/auth/login bloqueado; signup → onboarding/account"}],"commits":[{"sha":"62d8a37","repo":"coachid_app_frontend","date":"2026-08-12T17:50:23Z","author":"Marco Mendão","message":"native logout and auth ui without auth0 hosted pages"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:35:00Z","ended":"2026-08-12T17:38:00Z","summary":"Block Auth0 UL; signup → onboarding wizard"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-039-confirmacao-logout-nativa.md":{"id":"B-039","title":"Confirmação de logout nativa (sem página Auth0)","type":"bug","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":120000,"tags":["auth","logout","ui","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:40:00Z","completedAt":"2026-08-12T17:42:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-039-confirmacao-logout-nativa.md","description":"A confirmação de logout deve ser uma página da app (`/logout`). Confirmar → terminar sessão; Cancelar → raiz `/`. Não usar a página de confirmação do Auth0.","acceptanceCriteria":[{"checked":true,"text":"Link “Sair” abre `/logout` (confirmação nativa)"},{"checked":true,"text":"Confirmar limpa sessão e envia para `/login`"},{"checked":true,"text":"Cancelar redirecciona para `/`"},{"checked":true,"text":"Sem página de confirmação Auth0 na UI de logout"}],"acceptanceCriteriaRaw":"- [x] Link “Sair” abre `/logout` (confirmação nativa)\n- [x] Confirmar limpa sessão e envia para `/login`\n- [x] Cancelar redirecciona para `/`\n- [x] Sem página de confirmação Auth0 na UI de logout","reproSteps":"","fixCriteria":"- [x] Link “Sair” abre `/logout` (confirmação nativa)\n- [x] Confirmar limpa sessão e envia para `/login`\n- [x] Cancelar redirecciona para `/`\n- [x] Sem página de confirmação Auth0 na UI de logout","notes":"Parent: [S-018](../story.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:40:00Z","kind":"prompt","author":"Marco Mendão","summary":"Logout confirmation nativa; confirm=logout, cancel=/"},{"index":"2","when":"2026-08-12T17:42:00Z","kind":"feedback","author":"Marco Mendão","summary":"Página /logout + logout local sem Auth0 hosted"}],"commits":[{"sha":"62d8a37","repo":"coachid_app_frontend","date":"2026-08-12T17:50:23Z","author":"Marco Mendão","message":"native logout and auth ui without auth0 hosted pages"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:40:00Z","ended":"2026-08-12T17:42:00Z","summary":"Native /logout confirm; local session clear"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-040-nunca-usar-logout-auth0.md":{"id":"B-040","title":"Nunca usar logout Auth0 (só sessão local)","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":82000,"tags":["auth","logout","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:44:07Z","completedAt":"2026-08-12T17:45:29Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-040-nunca-usar-logout-auth0.md","description":"A aplicação não deve nunca mais chamar o logout hosted do Auth0 (`/auth/logout` / end_session / v2/logout). Todo o logout (UI e fluxos de convite) limpa só a sessão local da app.","acceptanceCriteria":[{"checked":true,"text":"Nenhum redirect/link para `/auth/logout` na UI/fluxos de menu"},{"checked":true,"text":"Middleware intercepta `/auth/logout` → `/logout` (confirmação nativa, sem Auth0)"},{"checked":true,"text":"Switch-account / resume de convite usam clear local"},{"checked":true,"text":"`logoutPathWithReturnTo` removido"}],"acceptanceCriteriaRaw":"- [x] Nenhum redirect/link para `/auth/logout` na UI/fluxos de menu\n- [x] Middleware intercepta `/auth/logout` → `/logout` (confirmação nativa, sem Auth0)\n- [x] Switch-account / resume de convite usam clear local\n- [x] `logoutPathWithReturnTo` removido","reproSteps":"","fixCriteria":"- [x] Nenhum redirect/link para `/auth/logout` na UI/fluxos de menu\n- [x] Middleware intercepta `/auth/logout` → `/logout` (confirmação nativa, sem Auth0)\n- [x] Switch-account / resume de convite usam clear local\n- [x] `logoutPathWithReturnTo` removido","notes":"Parent: [S-018](../story.md). Extends [B-039](B-039-confirmacao-logout-nativa.md).","promptFeedback":[{"index":"1","when":"2026-08-12T17:44:07Z","kind":"prompt","author":"Marco Mendão","summary":"App never uses Auth0 logout again"},{"index":"2","when":"2026-08-12T17:45:29Z","kind":"feedback","author":"Marco Mendão","summary":"Local clear helper; middleware blocks Auth0 logout; invite flows updated"},{"index":"3","when":"2026-08-12T17:45:54Z","kind":"prompt","author":"Marco Mendão","summary":"/auth/logout must show native logout confirmation page"},{"index":"4","when":"2026-08-12T17:46:10Z","kind":"feedback","author":"Marco Mendão","summary":"Middleware redirects /auth/logout → /logout"}],"commits":[{"sha":"62d8a37","repo":"coachid_app_frontend","date":"2026-08-12T17:50:23Z","author":"Marco Mendão","message":"native logout and auth ui without auth0 hosted pages"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:44:07Z","ended":"2026-08-12T17:45:29Z","summary":"Remove Auth0 logout; local clear everywhere"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-067-layout-pagina-login-shadcn-login-02.md":{"id":"T-067","title":"Layout da página de login (shadcn login-02)","type":"task","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","login","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-067-layout-pagina-login-shadcn-login-02.md","description":"Implementar a página de login com o bloco [login-02](https://ui.shadcn.com/blocks/login#login-02): grelha 2 colunas, logo/marca, formulário e painel de cover image.","acceptanceCriteria":[{"checked":true,"text":"Página de login usa layout login-02 (grid 2 colunas em lg+)"},{"checked":true,"text":"Cover image / visual de produto no painel direito (desktop)"},{"checked":true,"text":"Marca CoachID no topo do painel esquerdo"},{"checked":true,"text":"Componentes alinhados ao design system existente (shadcn/ui)"},{"checked":true,"text":"Mobile: formulário a full width sem cover"}],"acceptanceCriteriaRaw":"- [x] Página de login usa layout login-02 (grid 2 colunas em lg+)\n- [x] Cover image / visual de produto no painel direito (desktop)\n- [x] Marca CoachID no topo do painel esquerdo\n- [x] Componentes alinhados ao design system existente (shadcn/ui)\n- [x] Mobile: formulário a full width sem cover","reproSteps":"","fixCriteria":"","notes":"Parent: [S-018](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."},{"index":"2","when":"2026-08-12T16:35:10Z","kind":"prompt","author":"Marco Mendão","summary":"Cover direita login/registo = coachidbanner.png"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-068-ligar-formulario-login-auth0.md":{"id":"T-068","title":"Ligar formulário de login ao Auth0","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","login","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-068-ligar-formulario-login-auth0.md","description":"Ligar o formulário da nova UI de login ao fluxo Auth0 existente (Resource Owner / redirect / SDK da app — o que o produto já use), sem regressões no callback e sessão.","acceptanceCriteria":[{"checked":true,"text":"Submit do login dispara autenticação Auth0"},{"checked":true,"text":"Sessão Auth0 / cookies da app ficam válidos como hoje"},{"checked":true,"text":"Erros Auth0 mapeados para mensagens i18n no formulário"},{"checked":true,"text":"Redirect pós-login preserva deep links / returnTo quando aplicável"},{"checked":true,"text":"Não depende de Auth0 Organizations para o ecrã de login"}],"acceptanceCriteriaRaw":"- [x] Submit do login dispara autenticação Auth0\n- [x] Sessão Auth0 / cookies da app ficam válidos como hoje\n- [x] Erros Auth0 mapeados para mensagens i18n no formulário\n- [x] Redirect pós-login preserva deep links / returnTo quando aplicável\n- [x] Não depende de Auth0 Organizations para o ecrã de login","reproSteps":"","fixCriteria":"","notes":"Parent: [S-018](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-078-recuperar-password-no-login.md":{"id":"T-078","title":"Recuperar password no login (Auth0 change_password)","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":199000,"tags":["auth","login","password","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:04:00Z","completedAt":"2026-08-12T17:07:19Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-078-recuperar-password-no-login.md","description":"Adicionar “recuperar password” no ecrã de login: link no formulário, página `/forgot-password`, e pedido Auth0 `dbconnections/change_password` com feedback i18n.","acceptanceCriteria":[{"checked":true,"text":"Link “Forgot password?” / “Recuperar password” no formulário de login"},{"checked":true,"text":"Página pública `/forgot-password` no layout auth split"},{"checked":true,"text":"Submit envia email de reset via Auth0 change_password"},{"checked":true,"text":"Mensagem de sucesso genérica (não revela se o email existe)"},{"checked":true,"text":"Erros de configuração mapeados; i18n PT/EN"},{"checked":true,"text":"Voltar ao login a partir da página de recuperação"}],"acceptanceCriteriaRaw":"- [x] Link “Forgot password?” / “Recuperar password” no formulário de login\n- [x] Página pública `/forgot-password` no layout auth split\n- [x] Submit envia email de reset via Auth0 change_password\n- [x] Mensagem de sucesso genérica (não revela se o email existe)\n- [x] Erros de configuração mapeados; i18n PT/EN\n- [x] Voltar ao login a partir da página de recuperação","reproSteps":"","fixCriteria":"","notes":"Parent: [S-018](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:04:00Z","kind":"prompt","author":"Marco Mendão","summary":"Adiciona tbm um recuperar a password no login"},{"index":"2","when":"2026-08-12T17:07:19Z","kind":"feedback","author":"Marco Mendão","summary":"Implemented forgot-password page + Auth0 change_password from login"}],"commits":[{"sha":"6f5b71a","repo":"coachid_app_frontend","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add auth login signup forgot password and invites"},{"sha":"cde87fd","repo":"coachid_app_api","date":"2026-08-12T17:09:29Z","author":"Marco Mendão","message":"add org invite email and invitation token"},{"sha":"6192d7a","repo":"coachid-taskmark","date":"2026-08-12T17:09:30Z","author":"Marco Mendão","message":"sync taskmark board for auth ui and T-078"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:04:00Z","ended":"2026-08-12T17:07:19Z","summary":"Forgot-password link, `/forgot-password` page, Auth0 change_password + i18n"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-079-adaptar-login-registo-login-04.md":{"id":"T-079","title":"Adaptar login e registo ao layout shadcn login-04","type":"task","status":"done","priority":"medium","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":99000,"tags":["auth","login","signup","ui","shadcn"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:10:51Z","completedAt":"2026-08-12T17:12:30Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-079-adaptar-login-registo-login-04.md","description":"Trocar o layout auth de login-02 (split full-page) para [login-04](https://ui.shadcn.com/blocks/login#login-04): fundo muted centrado, card com formulário + imagem.","acceptanceCriteria":[{"checked":true,"text":"`/login` usa layout login-04 (card + cover)"},{"checked":true,"text":"`/signup` usa o mesmo layout login-04"},{"checked":true,"text":"Forgot-password e landing de convite alinhados ao mesmo shell"},{"checked":true,"text":"Mantém Auth0, i18n e fluxos existentes (sem OAuth social)"}],"acceptanceCriteriaRaw":"- [x] `/login` usa layout login-04 (card + cover)\n- [x] `/signup` usa o mesmo layout login-04\n- [x] Forgot-password e landing de convite alinhados ao mesmo shell\n- [x] Mantém Auth0, i18n e fluxos existentes (sem OAuth social)","reproSteps":"","fixCriteria":"","notes":"Parent: [S-018](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:10:51Z","kind":"prompt","author":"Marco Mendão","summary":"Adaptar login e registo para shadcn login-04"},{"index":"2","when":"2026-08-12T17:12:30Z","kind":"feedback","author":"Marco Mendão","summary":"Layout login-04 aplicado a login, signup, forgot e invite"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:10:51Z","ended":"2026-08-12T17:12:30Z","summary":"Auth shell → shadcn login-04 card layout"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-081-login-signup-button-spinners.md":{"id":"T-081","title":"Login e registo — loading com spinner nos botões","type":"task","status":"in_progress","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":12,"actualMs":757467,"tags":["auth","ui"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:30:55Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-081-login-signup-button-spinners.md","description":"Os botões de submit no login e no registo devem mostrar um spinner à frente da label (a label continua visível).","acceptanceCriteria":[{"checked":true,"text":"Login pending → spinner à frente da label do botão"},{"checked":true,"text":"Signup pending → spinner à frente da label do botão"},{"checked":true,"text":"Label do botão permanece visível durante o loading"}],"acceptanceCriteriaRaw":"- [x] Login pending → spinner à frente da label do botão\n- [x] Signup pending → spinner à frente da label do botão\n- [x] Label do botão permanece visível durante o loading","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-08-14T14:30:55Z","kind":"prompt","author":"Marco Mendão","summary":"Login/signup button loading should be spinners"},{"index":"2","when":"2026-08-14T14:30:55Z","kind":"feedback","author":"Marco Mendão","summary":"IconLoader2 animate-spin on LoginForm and SignupForm"},{"index":"3","when":"2026-08-14T14:34:00Z","kind":"prompt","author":"Marco Mendão","summary":"Keep button label visible with spinner in front"}],"commits":[{"sha":"03cf300","repo":"coachid_app_frontend","date":"2026-08-14T14:43:32Z","author":"Marco Mendão","message":"polish auth signup login logout ui"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:30:55Z","ended":"—","summary":"In progress: spinner loading on auth submit buttons"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-082-logout-sem-cover-imagem.md":{"id":"T-082","title":"Logout — confirmação a página inteira sem cover","type":"task","status":"in_progress","priority":"medium","size":"XS","points":1,"estimateMinutes":25,"actualMinutes":6,"actualMs":400467,"tags":["auth","logout","ui"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:36:52Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-082-logout-sem-cover-imagem.md","description":"A página de terminar sessão não deve mostrar a imagem do lado direito; a mensagem de confirmação ocupa o cartão/layout completo.","acceptanceCriteria":[{"checked":true,"text":"sem cover image"},{"checked":true,"text":"Confirmação em coluna única (showCover=false)"}],"acceptanceCriteriaRaw":"- [x] sem cover image\n- [x] Confirmação em coluna única (showCover=false)","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-08-14T14:36:52Z","kind":"prompt","author":"Marco Mendão","summary":"Logout page should not show right image; confirmation full page"},{"index":"2","when":"2026-08-14T14:36:52Z","kind":"feedback","author":"Marco Mendão","summary":"AuthCardLayout showCover=false on logout"}],"commits":[{"sha":"03cf300","repo":"coachid_app_frontend","date":"2026-08-14T14:43:32Z","author":"Marco Mendão","message":"polish auth signup login logout ui"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:36:52Z","ended":"—","summary":"In progress: logout full-width confirm without cover"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-083-auth-logo-light-cid-azul.md":{"id":"T-083","title":"Auth light — logo cid_azul nas páginas login/logout/registo","type":"task","status":"done","priority":"low","size":"XS","points":1,"estimateMinutes":15,"actualMinutes":0,"actualMs":0,"tags":["auth","ui","branding"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-018","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:38:31Z","completedAt":"2026-08-14T14:38:31Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-083-auth-logo-light-cid-azul.md","description":"Na versão light do tema, as páginas de auth (login, logout, registo) usam em vez de .","acceptanceCriteria":[{"checked":true,"text":"AuthCardLayout light mode usa"},{"checked":true,"text":"Dark mode mantém"}],"acceptanceCriteriaRaw":"- [x] AuthCardLayout light mode usa \n- [x] Dark mode mantém","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-08-14T14:38:31Z","kind":"prompt","author":"Marco Mendão","summary":"Use cid_azul.png for light theme on login/logout/signup"},{"index":"2","when":"2026-08-14T14:38:31Z","kind":"feedback","author":"Marco Mendão","summary":"Swapped light logo in AuthCardLayout"}],"commits":[{"sha":"03cf300","repo":"coachid_app_frontend","date":"2026-08-14T14:43:32Z","author":"Marco Mendão","message":"polish auth signup login logout ui"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:38:31Z","ended":"2026-08-14T14:38:31Z","summary":"Auth light logo → cid_azul.png"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md":{"id":"S-019","title":"Nova UI de registo normal (shadcn signup-02) com Auth0","type":"story","status":"done","priority":"high","size":"L","points":8,"estimateMinutes":310,"actualMinutes":2,"actualMs":120000,"tags":["auth","signup","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-012","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md","userStory":"Como novo utilizador, quero registar-me através de uma página de signup moderna (padrão shadcn signup-02), para criar a minha conta CoachID com Auth0 por detrás.","acceptanceCriteria":[{"checked":true,"text":"Existe uma página/rota de registo **normal** (sem convite) com layout **login-04** (mesmo shell do login)"},{"checked":true,"text":"A marca CoachID aparece no ecrã de registo"},{"checked":true,"text":"O registo cria utilizador via **Auth0** e integra com o onboarding/setup actual"},{"checked":true,"text":"Link entre login ↔ registo nas novas UIs"},{"checked":true,"text":"i18n PT/EN"},{"checked":true,"text":"Responsivo (mobile / desktop com cover no card)"}],"acceptanceCriteriaRaw":"- [x] Existe uma página/rota de registo **normal** (sem convite) com layout **login-04** (mesmo shell do login)\n- [x] A marca CoachID aparece no ecrã de registo\n- [x] O registo cria utilizador via **Auth0** e integra com o onboarding/setup actual\n- [x] Link entre login ↔ registo nas novas UIs\n- [x] i18n PT/EN\n- [x] Responsivo (mobile / desktop com cover no card)","tasksMarkdown":"- [T-069](items/T-069-layout-pagina-registo-shadcn-signup-02.md) — Layout da página de registo normal (shadcn signup-02)\n- [T-070](items/T-070-ligar-formulario-registo-auth0.md) — Ligar formulário de registo normal ao Auth0","children":[{"id":"T-069","title":"Layout da página de registo normal (shadcn signup-02)","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-069-layout-pagina-registo-shadcn-signup-02.md"},{"id":"T-070","title":"Ligar formulário de registo normal ao Auth0","type":"task","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-070-ligar-formulario-registo-auth0.md"}],"promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic — UI login/registo shadcn + fluxo convite org (SendGrid, registo por convite, confirmação, erro utilizador errado)."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:46:38Z","summary":"shared-batch parent rollup (0 min; effort on tasks)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-069-layout-pagina-registo-shadcn-signup-02.md":{"id":"T-069","title":"Layout da página de registo normal (shadcn signup-02)","type":"task","status":"done","priority":"high","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","signup","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-019","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-069-layout-pagina-registo-shadcn-signup-02.md","description":"Implementar a página de registo normal com o bloco [signup-02](https://ui.shadcn.com/blocks/signup#signup-02).","acceptanceCriteria":[{"checked":true,"text":"Página de signup usa layout signup-02 (grid 2 colunas em lg+)"},{"checked":true,"text":"Cover image no painel direito (desktop)"},{"checked":true,"text":"Marca CoachID no painel do formulário"},{"checked":true,"text":"Campos de registo coerentes com os requisitos Auth0 da app (email, password, nome se aplicável)"},{"checked":true,"text":"Link para a nova página de login"}],"acceptanceCriteriaRaw":"- [x] Página de signup usa layout signup-02 (grid 2 colunas em lg+)\n- [x] Cover image no painel direito (desktop)\n- [x] Marca CoachID no painel do formulário\n- [x] Campos de registo coerentes com os requisitos Auth0 da app (email, password, nome se aplicável)\n- [x] Link para a nova página de login","reproSteps":"","fixCriteria":"","notes":"Parent: [S-019](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-070-ligar-formulario-registo-auth0.md":{"id":"T-070","title":"Ligar formulário de registo normal ao Auth0","type":"task","status":"done","priority":"high","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","signup","ui","shadcn","auth0"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-019","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-070-ligar-formulario-registo-auth0.md","description":"Ligar o formulário de registo normal ao Auth0 (signup / create user + login) e ao fluxo pós-registo (setup / onboarding) já existente.","acceptanceCriteria":[{"checked":true,"text":"Submit cria conta Auth0 e inicia sessão"},{"checked":true,"text":"Validações de password / email alinhadas ao Auth0 e i18n"},{"checked":true,"text":"Pós-registo entra no setup/onboarding actual sem regressão"},{"checked":true,"text":"Não requer token de convite (fluxo «normal»)"}],"acceptanceCriteriaRaw":"- [x] Submit cria conta Auth0 e inicia sessão\n- [x] Validações de password / email alinhadas ao Auth0 e i18n\n- [x] Pós-registo entra no setup/onboarding actual sem regressão\n- [x] Não requer token de convite (fluxo «normal»)","reproSteps":"","fixCriteria":"","notes":"Parent: [S-019](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md":{"id":"S-020","title":"Fluxo de convite para organização (email, registo, login e confirmação)","type":"story","status":"done","priority":"critical","size":"XL","points":35,"estimateMinutes":1225,"actualMinutes":86,"actualMs":5219401,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"E-012","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T15:22:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md","userStory":"Como owner/admin de uma organização, quero que o convite por email chegue ao destinatário e o leve ao fluxo correcto (registo por convite, ou login + confirmação, ou só confirmação se já estiver autenticado), para que o membership seja aceite de forma clara e o convidado aterre no lineup da organização — corrigindo a lacuna criada ao sair das Auth0 Organizations.","acceptanceCriteria":[{"checked":true,"text":"Existe template SendGrid para convite à organização (copy + link com token/id do convite)"},{"checked":true,"text":"Ao criar / reenviar convite, a API envia o email (não só persiste em Mongo)"},{"checked":true,"text":"O link do email abre a app no fluxo de convite correcto"},{"checked":true,"text":"Abre o **registo por convite** (UI signup-02 ou variante)"},{"checked":true,"text":"Email vem **readonly** e pré-preenchido"},{"checked":true,"text":"Mostra informação de que o utilizador será adicionado à organização X"},{"checked":true,"text":"Após registo Auth0, o convite é claimado / aceite e redirecciona para o lineup da org"},{"checked":true,"text":"Em vez do registo, pede **credenciais de login**"},{"checked":true,"text":"Após login, mostra **página de confirmação** para aceitar o convite"},{"checked":true,"text":"Ao aceitar, redirecciona para a página inicial (lineup) da organização"},{"checked":true,"text":"Se o convite pertence ao utilizador da sessão: mostra **só a página de confirmação**"},{"checked":true,"text":"Se o convite **não** pertence ao utilizador logado: página de erro com imagem/estado visual, mensagem a explicar que não foi convidado para esta organização, botão para **login com outra conta**, e opção para **ir ao início** da app"},{"checked":true,"text":"Aceitar o convite (quando válido) cria/actualiza membership e redirecciona para o lineup da org"}],"acceptanceCriteriaRaw":"### Email\n- [x] Existe template SendGrid para convite à organização (copy + link com token/id do convite)\n- [x] Ao criar / reenviar convite, a API envia o email (não só persiste em Mongo)\n- [x] O link do email abre a app no fluxo de convite correcto\n\n### Destinatário sem conta\n- [x] Abre o **registo por convite** (UI signup-02 ou variante)\n- [x] Email vem **readonly** e pré-preenchido\n- [x] Mostra informação de que o utilizador será adicionado à organização X\n- [x] Após registo Auth0, o convite é claimado / aceite e redirecciona para o lineup da org\n\n### Destinatário com conta (não autenticado)\n- [x] Em vez do registo, pede **credenciais de login**\n- [x] Após login, mostra **página de confirmação** para aceitar o convite\n- [x] Ao aceitar, redirecciona para a página inicial (lineup) da organização\n\n### Destinatário já autenticado\n- [x] Se o convite pertence ao utilizador da sessão: mostra **só a página de confirmação**\n- [x] Se o convite **não** pertence ao utilizador logado: página de erro com imagem/estado visual, mensagem a explicar que não foi convidado para esta organização, botão para **login com outra conta**, e opção para **ir ao início** da app\n- [x] Aceitar o convite (quando válido) cria/actualiza membership e redirecciona para o lineup da org","tasksMarkdown":"- [T-071](items/T-071-template-sendgrid-convite-organizacao.md) — Template SendGrid de convite à organização\n- [T-072](items/T-072-api-enviar-email-convite-create-resend.md) — API: enviar email no create/resend de convite\n- [T-073](items/T-073-rota-landing-convite-resolver-estado.md) — Rota landing de convite e resolução de estado\n- [T-074](items/T-074-registo-por-convite-email-readonly.md) — Registo por convite — email readonly + contexto da org\n- [T-075](items/T-075-convite-utilizador-existente-login-confirmacao.md) — Convite: utilizador existente — login e página de confirmação\n- [T-076](items/T-076-convite-ja-logado-pagina-confirmacao.md) — Convite: já logado e email corresponde — só confirmação\n- [T-077](items/T-077-convite-utilizador-errado-pagina-erro.md) — Convite: utilizador logado errado — página de erro\n- [T-080](items/T-080-registo-convite-password-confirmar.md) — Registo por convite — password + confirmar password\n- [B-041](items/B-041-registo-convite-conta-ja-existe.md) — Registo por convite falha com “conta já existe”\n- [B-042](items/B-042-email-convite-sem-assunto.md) — Email de convite sem assunto\n- [B-043](items/B-043-resend-convite-404-api-main.md) — Resend convite 404 na API main\n- [B-044](items/B-044-registo-convite-redirect-wizard.md) — Após registo por convite volta ao link inválido em vez do wizard\n- [B-045](items/B-045-resend-convite-accepted-fake-id-500.md) — Resend convite 500 com id fake accepted-auth0\n- [B-046](items/B-046-invite-landing-cookie-rsc-500.md) — Invite landing 500 ao setar cookie no RSC","children":[{"id":"B-041","title":"Registo por convite falha com “conta já existe”","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-041-registo-convite-conta-ja-existe.md"},{"id":"B-042","title":"Email de convite sem assunto","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-042-email-convite-sem-assunto.md"},{"id":"B-043","title":"Resend convite 404 na API main","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-043-resend-convite-404-api-main.md"},{"id":"B-044","title":"Após registo por convite volta ao link inválido em vez do wizard","type":"bug","status":"done","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-044-registo-convite-redirect-wizard.md"},{"id":"B-045","title":"Resend convite 500 com id fake accepted-auth0","type":"bug","status":"in_progress","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-045-resend-convite-accepted-fake-id-500.md"},{"id":"B-046","title":"Invite landing 500 ao setar cookie no RSC","type":"bug","status":"in_progress","priority":"high","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-046-invite-landing-cookie-rsc-500.md"},{"id":"T-071","title":"Template SendGrid de convite à organização","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-071-template-sendgrid-convite-organizacao.md"},{"id":"T-073","title":"Rota landing de convite e resolução de estado","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-073-rota-landing-convite-resolver-estado.md"},{"id":"T-074","title":"Registo por convite — email readonly + contexto da org","type":"task","status":"done","priority":"critical","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-074-registo-por-convite-email-readonly.md"},{"id":"T-080","title":"Registo por convite — password + confirmar password","type":"task","status":"in_progress","priority":"medium","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-080-registo-convite-password-confirmar.md"}],"promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"/create-epic — UI login/registo shadcn + fluxo convite org (SendGrid, registo por convite, confirmação, erro utilizador errado)."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:46:38Z","summary":"shared-batch parent rollup (0 min; effort on tasks)"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-041-registo-convite-conta-ja-existe.md":{"id":"B-041","title":"Registo por convite falha com “conta já existe”","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":105000,"tags":["auth","convites","signup","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:52:31Z","completedAt":"2026-08-12T17:54:16Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-041-registo-convite-conta-ja-existe.md","description":"Ao registar um convidado sem conta na app, o formulário devolve sempre “Já existe uma conta com este email. Iniciar sessão” (Auth0 `user_exists`), bloqueando o fluxo.","acceptanceCriteria":[{"checked":true,"text":"Signup idempotente: se Auth0 já tem o email, tenta login com a password submetida"},{"checked":true,"text":"Com token de convite válido e sem conta na app: pode completar identidade órfã no Auth0 (set password) e seguir"},{"checked":true,"text":"`accountExists` no convite usa match de email case-insensitive"},{"checked":true,"text":"Convidado novo consegue registar e chegar à confirmação/lineup"}],"acceptanceCriteriaRaw":"- [x] Signup idempotente: se Auth0 já tem o email, tenta login com a password submetida\n- [x] Com token de convite válido e sem conta na app: pode completar identidade órfã no Auth0 (set password) e seguir\n- [x] `accountExists` no convite usa match de email case-insensitive\n- [x] Convidado novo consegue registar e chegar à confirmação/lineup","reproSteps":"","fixCriteria":"- [x] Signup idempotente: se Auth0 já tem o email, tenta login com a password submetida\n- [x] Com token de convite válido e sem conta na app: pode completar identidade órfã no Auth0 (set password) e seguir\n- [x] `accountExists` no convite usa match de email case-insensitive\n- [x] Convidado novo consegue registar e chegar à confirmação/lineup","notes":"Parent: [S-020](../story.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:52:31Z","kind":"prompt","author":"Marco Mendão","summary":"Invite signup always shows account already exists"},{"index":"2","when":"2026-08-12T17:54:16Z","kind":"feedback","author":"Marco Mendão","summary":"Idempotent signup + invite orphan password claim; case-insensitive accountExists"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:52:31Z","ended":"2026-08-12T17:54:16Z","summary":"Fix invite signup Auth0 user_exists recovery"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-042-email-convite-sem-assunto.md":{"id":"B-042","title":"Email de convite sem assunto","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":5,"actualMinutes":3,"actualMs":183000,"tags":["auth","convites","sendgrid","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T17:55:18Z","completedAt":"2026-08-12T17:58:21Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-042-email-convite-sem-assunto.md","description":"O email de convite chega sem assunto. O SendGrid Dynamic Template ignora o `subject` da API se o Subject do template não estiver como `{{subject}}` / `{{{subject}}}`.","acceptanceCriteria":[{"checked":true,"text":"Convite enviado com assunto explícito (HTML mail, não depende do Subject do template SG)"},{"checked":true,"text":"Assunto no estilo `CoachID - Foi convidado para aderir à organização {X}`"},{"checked":true,"text":"Corpo do email mantém o layout do template de convite"}],"acceptanceCriteriaRaw":"- [x] Convite enviado com assunto explícito (HTML mail, não depende do Subject do template SG)\n- [x] Assunto no estilo `CoachID - Foi convidado para aderir à organização {X}`\n- [x] Corpo do email mantém o layout do template de convite","reproSteps":"","fixCriteria":"- [x] Convite enviado com assunto explícito (HTML mail, não depende do Subject do template SG)\n- [x] Assunto no estilo `CoachID - Foi convidado para aderir à organização {X}`\n- [x] Corpo do email mantém o layout do template de convite","notes":"Parent: [S-020](../story.md)","promptFeedback":[{"index":"1","when":"2026-08-12T17:55:18Z","kind":"prompt","author":"Marco Mendão","summary":"Invite email arrives without subject; add subject"},{"index":"2","when":"2026-08-12T17:58:21Z","kind":"feedback","author":"Marco Mendão","summary":"HTML send with subject; no SG template subject dependency"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T17:55:18Z","ended":"2026-08-12T17:58:21Z","summary":"HTML invite mail with explicit subject"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-043-resend-convite-404-api-main.md":{"id":"B-043","title":"Resend convite 404 na API main","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":87000,"tags":["auth","convites","api","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T10:16:33Z","completedAt":"2026-08-14T10:18:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-043-resend-convite-404-api-main.md","description":"`POST .../members/invitations/:id/resend` devolve Nest 404 (`Cannot POST`) porque a API `main` em `:6001` não tinha a rota (só existia na worktree-1).","acceptanceCriteria":[{"checked":true,"text":"Rota resend na API main"},{"checked":true,"text":"Envio HTML do email de convite com assunto"},{"checked":true,"text":"Token no schema + create/resend geram/enviam email"},{"checked":true,"text":"GET/POST `/organization-invitations/:token` (landing + accept)"}],"acceptanceCriteriaRaw":"- [x] Rota resend na API main\n- [x] Envio HTML do email de convite com assunto\n- [x] Token no schema + create/resend geram/enviam email\n- [x] GET/POST `/organization-invitations/:token` (landing + accept)","reproSteps":"","fixCriteria":"- [x] Rota resend na API main\n- [x] Envio HTML do email de convite com assunto\n- [x] Token no schema + create/resend geram/enviam email\n- [x] GET/POST `/organization-invitations/:token` (landing + accept)","notes":"Parent: [S-020](../story.md)","promptFeedback":[{"index":"1","when":"2026-08-14T10:16:33Z","kind":"prompt","author":"Marco Mendão","summary":"Terminal 404 on invite resend"},{"index":"2","when":"2026-08-14T10:18:00Z","kind":"feedback","author":"Marco Mendão","summary":"Ported resend + invite HTML mail to main API"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T10:16:33Z","ended":"2026-08-14T10:18:00Z","summary":"Port invite resend route to main API"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-044-registo-convite-redirect-wizard.md":{"id":"B-044","title":"Após registo por convite volta ao link inválido em vez do wizard","type":"bug","status":"done","priority":"high","size":"S","points":2,"estimateMinutes":80,"actualMinutes":1,"actualMs":81000,"tags":["auth","convites","signup","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T10:29:39Z","completedAt":"2026-08-14T10:31:00Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-044-registo-convite-redirect-wizard.md","description":"Depois do registo por convite, a app redireccionava para `/invite/{token}` e mostrava “Convite indisponível”. O `claimPendingInvitations` na API main aceitava o convite no `POST /users/me`, e o signup usava `returnTo` do convite.","acceptanceCriteria":[{"checked":true,"text":"`claimPendingInvitations` é no-op (aceitação explícita)"},{"checked":true,"text":"Signup com `inviteToken` aceita o convite e activa a org"},{"checked":true,"text":"Se a org já tem equipa → lineup (salta onboarding); senão setup/onboarding"},{"checked":true,"text":"Convite já `accepted` + sessão correcta → redirect `/` (não “indisponível”)"}],"acceptanceCriteriaRaw":"- [x] `claimPendingInvitations` é no-op (aceitação explícita)\n- [x] Signup com `inviteToken` aceita o convite e activa a org\n- [x] Se a org já tem equipa → lineup (salta onboarding); senão setup/onboarding\n- [x] Convite já `accepted` + sessão correcta → redirect `/` (não “indisponível”)","reproSteps":"","fixCriteria":"- [x] `claimPendingInvitations` é no-op (aceitação explícita)\n- [x] Signup com `inviteToken` aceita o convite e activa a org\n- [x] Se a org já tem equipa → lineup (salta onboarding); senão setup/onboarding\n- [x] Convite já `accepted` + sessão correcta → redirect `/` (não “indisponível”)","notes":"Parent: [S-020](../story.md)","promptFeedback":[{"index":"1","when":"2026-08-14T10:29:39Z","kind":"prompt","author":"Marco Mendão","summary":"After invite signup redirect to root wizard, not invalid invite"},{"index":"2","when":"2026-08-14T10:31:00Z","kind":"feedback","author":"Marco Mendão","summary":"No auto-claim; invite signup → accept + onboarding"},{"index":"3","when":"2026-08-14T10:38:00Z","kind":"prompt","author":"Marco Mendão","summary":"After invite signup, if org has team skip wizard and open that team"},{"index":"4","when":"2026-08-14T10:38:30Z","kind":"feedback","author":"Marco Mendão","summary":"Invite signup uses ResolveAppHomePath on accepted org"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T10:29:39Z","ended":"2026-08-14T10:31:00Z","summary":"Fix invite signup redirect to onboarding"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-045-resend-convite-accepted-fake-id-500.md":{"id":"B-045","title":"Resend convite 500 com id fake accepted-auth0","type":"bug","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":33,"actualMs":2012467,"tags":["auth","convites","api","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:10:00Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-045-resend-convite-accepted-fake-id-500.md","description":"","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"API main `createInvitation` auto-adicionava utilizadores existentes e devolvia `id: accepted-${auth0Sub}`. O UI fazia resend desse id → Cast to ObjectId failed → 500. Depois do fix API, o mesmo id stale na UI dava 400 `Invalid invitation id`.","promptFeedback":[{"index":"1","when":"2026-08-14T14:06:00Z","kind":"prompt","author":"Marco Mendão","summary":"Terminal 500 on invite resend (accepted-auth0 fake id)"},{"index":"2","when":"2026-08-14T14:10:00Z","kind":"feedback","author":"Marco Mendão","summary":"Align createInvitation with invite flow; validate ObjectId on resend/revoke"},{"index":"3","when":"2026-08-14T14:10:30Z","kind":"prompt","author":"Marco Mendão","summary":"FE still shows Invalid invitation id JSON on resend of stale accepted-* row"},{"index":"4","when":"2026-08-14T14:12:00Z","kind":"feedback","author":"Marco Mendão","summary":"FE filters fake ids + refreshes members list on stale resend"},{"index":"5","when":"2026-08-14T14:16:00Z","kind":"prompt","author":"Marco Mendão","summary":"Still Invalid invitation id — was revoke; React kept stale accepted-* state"},{"index":"6","when":"2026-08-14T14:17:30Z","kind":"feedback","author":"Marco Mendão","summary":"Sync initialData; revoke short-circuits fake ids; clear on revoke/resend"}],"commits":[{"sha":"148604c","repo":"coachid_app_frontend","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite cookie rsc and stale invite ui"},{"sha":"4ce00a4","repo":"coachid_app_api","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite email send and membership invite"},{"sha":"4856ada","repo":"coachid_app_api","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite pending flow and resend ids"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:10:00Z","ended":"—","summary":"In progress: fix createInvitation auto-accept + resend CastError"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-046-invite-landing-cookie-rsc-500.md":{"id":"B-046","title":"Invite landing 500 ao setar cookie no RSC","type":"bug","status":"in_progress","priority":"high","size":"S","points":2,"estimateMinutes":55,"actualMinutes":21,"actualMs":1292467,"tags":["auth","convites","bug"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:22:00Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-046-invite-landing-cookie-rsc-500.md","description":"","acceptanceCriteria":[],"acceptanceCriteriaRaw":"","reproSteps":"","fixCriteria":"","notes":"`logoutAndResumeInvite` corria no render da page → Next: “Cookies can only be modified in a Server Action or Route Handler”.","promptFeedback":[{"index":"1","when":"2026-08-14T14:21:00Z","kind":"prompt","author":"Marco Mendão","summary":"Terminal 500 cookies().set in InviteLandingPage"},{"index":"2","when":"2026-08-14T14:22:00Z","kind":"feedback","author":"Marco Mendão","summary":"Redirect to switch-account route; resume as route handler"}],"commits":[{"sha":"148604c","repo":"coachid_app_frontend","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite cookie rsc and stale invite ui"},{"sha":"4ce00a4","repo":"coachid_app_api","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite email send and membership invite"},{"sha":"4856ada","repo":"coachid_app_api","date":"2026-08-14T14:24:42Z","author":"Marco Mendão","message":"fix invite pending flow and resend ids"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:22:00Z","ended":"—","summary":"In progress: fix invite cookie mutation outside RSC"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-071-template-sendgrid-convite-organizacao.md":{"id":"T-071","title":"Template SendGrid de convite à organização","type":"task","status":"done","priority":"critical","size":"S","points":2,"estimateMinutes":80,"actualMinutes":2,"actualMs":172000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T16:25:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-071-template-sendgrid-convite-organizacao.md","description":"Definir e documentar o dynamic template SendGrid para convite de organização (variáveis: org name/avatar, inviter name/avatar, accept URL, locale). Adicionar env keys em `.env.example`.","acceptanceCriteria":[{"checked":true,"text":"Template SendGrid criado/documentado (ID + variáveis dinâmicas)"},{"checked":true,"text":"Env example com `SENDGRID_TEMPLATE_ORG_INVITE` (ou nome acordado)"},{"checked":true,"text":"Copy PT (e EN se o template for multi-locale / dois templates)"},{"checked":true,"text":"Link de aceitação inclui identificador seguro do convite"},{"checked":true,"text":"Template mostra nome e avatar da organização"},{"checked":true,"text":"Template mostra nome e avatar de quem convidou"},{"checked":true,"text":"Assunto do email no estilo `CoachID - Foi convidado para aderir à organização {X}`"}],"acceptanceCriteriaRaw":"- [x] Template SendGrid criado/documentado (ID + variáveis dinâmicas)\n- [x] Env example com `SENDGRID_TEMPLATE_ORG_INVITE` (ou nome acordado)\n- [x] Copy PT (e EN se o template for multi-locale / dois templates)\n- [x] Link de aceitação inclui identificador seguro do convite\n- [x] Template mostra nome e avatar da organização\n- [x] Template mostra nome e avatar de quem convidou\n- [x] Assunto do email no estilo `CoachID - Foi convidado para aderir à organização {X}`","reproSteps":"","fixCriteria":"","notes":"Parent: [S-020](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."},{"index":"2","when":"2026-08-12T15:21:23Z","kind":"prompt","author":"Marco Mendão","summary":"Template convite: incluir nome/avatar da org e do convidador"},{"index":"3","when":"2026-08-12T15:22:58Z","kind":"feedback","author":"Marco Mendão","summary":"Template com nome/avatar org + convidador"},{"index":"4","when":"2026-08-12T15:25:01Z","kind":"prompt","author":"Marco Mendão","summary":"Melhorar copy do template de convite — mais expressivo"},{"index":"5","when":"2026-08-12T15:25:40Z","kind":"feedback","author":"Marco Mendão","summary":"Copy do template mais expressivo"},{"index":"6","when":"2026-08-12T16:25:20Z","kind":"prompt","author":"Marco Mendão","summary":"Assunto do email: CoachID - Foi convidado para aderir à organização X"},{"index":"7","when":"2026-08-12T16:25:58Z","kind":"feedback","author":"Marco Mendão","summary":"Assunto do email com nome da organização"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:46:38Z","summary":"shared-batch: 0 of 7min by points — E-012 worktree-1"},{"session":"2","actor":"Marco Mendão","started":"2026-08-12T15:21:23Z","ended":"2026-08-12T15:22:58Z","summary":"Enriched invite email template with org + inviter name/avatar"},{"session":"3","actor":"Marco Mendão","started":"2026-08-12T15:25:01Z","ended":"2026-08-12T15:25:40Z","summary":"Improved invite email copy (context + CTA)"},{"session":"4","actor":"Marco Mendão","started":"2026-08-12T16:25:20Z","ended":"2026-08-12T16:25:58Z","summary":"Invite email subject with organization name"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-073-rota-landing-convite-resolver-estado.md":{"id":"T-073","title":"Rota landing de convite e resolução de estado","type":"task","status":"done","priority":"critical","size":"M","points":3,"estimateMinutes":115,"actualMinutes":1,"actualMs":60000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-073-rota-landing-convite-resolver-estado.md","description":"Criar rota pública (ex. `/invite/[token]`) que resolve o convite e decide: signup por convite | login+confirmação | confirmação | erro (inválido/expirado/utilizador errado).","acceptanceCriteria":[{"checked":true,"text":"Rota de landing de convite implementada"},{"checked":true,"text":"Resolve convite pending válido vs expirado/revogado"},{"checked":true,"text":"Branching correcto com base em: sessão actual, existência de user Auth0/app para o email"},{"checked":true,"text":"Deep link seguro (token não adivinhável)"}],"acceptanceCriteriaRaw":"- [x] Rota de landing de convite implementada\n- [x] Resolve convite pending válido vs expirado/revogado\n- [x] Branching correcto com base em: sessão actual, existência de user Auth0/app para o email\n- [x] Deep link seguro (token não adivinhável)","reproSteps":"","fixCriteria":"","notes":"Parent: [S-020](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-074-registo-por-convite-email-readonly.md":{"id":"T-074","title":"Registo por convite — email readonly + contexto da org","type":"task","status":"done","priority":"critical","size":"L","points":5,"estimateMinutes":195,"actualMinutes":1,"actualMs":60000,"tags":["auth","convites","sendgrid","organizacoes","signup","login"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-12","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-12T14:46:38Z","completedAt":"2026-08-12T14:53:58Z","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-074-registo-por-convite-email-readonly.md","description":"UI de registo por convite (base signup-02): email readonly, mensagem de adição à organização, submit Auth0 signup, depois aceitar/claim e redirect ao lineup.","acceptanceCriteria":[{"checked":true,"text":"Formulário de registo por convite (layout alinhado a signup-02)"},{"checked":true,"text":"Email readonly e pré-preenchido do convite"},{"checked":true,"text":"Informação visível da organização destino"},{"checked":true,"text":"Pós-registo: membership activo + redirect lineup da org"},{"checked":true,"text":"i18n"}],"acceptanceCriteriaRaw":"- [x] Formulário de registo por convite (layout alinhado a signup-02)\n- [x] Email readonly e pré-preenchido do convite\n- [x] Informação visível da organização destino\n- [x] Pós-registo: membership activo + redirect lineup da org\n- [x] i18n","reproSteps":"","fixCriteria":"","notes":"Parent: [S-020](../story.md) · Epic: [E-012](../../../epic.md)","promptFeedback":[{"index":"1","when":"2026-08-12T14:11:53Z","kind":"prompt","author":"Marco Mendão","summary":"Criar tarefa no âmbito do epic Auth UI / convites."},{"index":"2","when":"2026-08-12T16:40:03Z","kind":"prompt","author":"Marco Mendão","summary":"Registo por convite: card org+convidador (avatar/nome); esconder assistente em login/signup"}],"commits":[],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-12T14:46:38Z","ended":"2026-08-12T14:47:38Z","summary":"shared-batch: 1 of 7min by points — E-012 worktree-1"}]},"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-080-registo-convite-password-confirmar.md":{"id":"T-080","title":"Registo por convite — password + confirmar password","type":"task","status":"in_progress","priority":"medium","size":"S","points":2,"estimateMinutes":55,"actualMinutes":18,"actualMs":1106467,"tags":["auth","convites","signup"],"owner":"","reporters":[{"name":"Marco Mendão","email":"marco.mendao@betacode.tech","initials":"MM"}],"resolvers":[],"blocked":false,"cancelled":false,"parent":"S-020","epic":"E-012","created":"2026-08-14","updated":"2026-08-14T14:43:32.467Z","startedAt":"2026-08-14T14:25:06Z","completedAt":"","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-080-registo-convite-password-confirmar.md","description":"No fluxo de criar conta a partir do convite, o utilizador deve introduzir a password e confirmá-la no campo seguinte.","acceptanceCriteria":[{"checked":true,"text":"Signup (convite) mostra password e confirmar password"},{"checked":true,"text":"Submit falha com erro claro se as passwords não coincidirem"},{"checked":true,"text":"Passwords coincidentes seguem o fluxo de criação de conta existente"}],"acceptanceCriteriaRaw":"- [x] Signup (convite) mostra password e confirmar password\n- [x] Submit falha com erro claro se as passwords não coincidirem\n- [x] Passwords coincidentes seguem o fluxo de criação de conta existente","reproSteps":"","fixCriteria":"","notes":"","promptFeedback":[{"index":"1","when":"2026-08-14T14:25:06Z","kind":"prompt","author":"Marco Mendão","summary":"Invite signup needs password + confirm password fields"},{"index":"2","when":"2026-08-14T14:26:00Z","kind":"feedback","author":"Marco Mendão","summary":"Added confirmPassword field + server mismatch validation"}],"commits":[{"sha":"03cf300","repo":"coachid_app_frontend","date":"2026-08-14T14:43:32Z","author":"Marco Mendão","message":"polish auth signup login logout ui"}],"workLog":[{"session":"1","actor":"Marco Mendão","started":"2026-08-14T14:25:06Z","ended":"—","summary":"In progress: add confirm password to invite signup"}]}},"refsById":{"E-001":{"kind":"epic","id":"E-001","title":"Motor de exercícios","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/epic.md"},"B-011":{"kind":"item","id":"B-011","title":"Texto no vídeo do exercício usa fonte diferente do portal","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-011-texto-video-exercicio-fonte-diferente.md","itemType":"bug"},"B-012":{"kind":"item","id":"B-012","title":"Bola teleporta ao associar a jogador durante animação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-012-bola-teleporta-ao-associar-durante-animacao.md","itemType":"bug"},"B-016":{"kind":"item","id":"B-016","title":"Editor — copy/paste não funciona com múltiplos elementos seleccionados","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-016-copy-paste-multipla-selecao-elementos.md","itemType":"bug"},"B-022":{"kind":"item","id":"B-022","title":"Exercise editor — PageHeader maximum update depth exceeded","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-022-exercise-editor-pageheader-infinite-loop.md","itemType":"bug"},"B-026":{"kind":"item","id":"B-026","title":"/pub/media/*.woff2 404 ao exportar/renderizar exercícios","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-026-pub-media-woff2-404.md","itemType":"bug"},"B-027":{"kind":"item","id":"B-027","title":"Editor — copy/paste de seta/curva perde pontos de controlo da curvatura","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/B-027-editor-copy-paste-seta-perde-pontos-controlo-curvatura.md","itemType":"bug"},"T-022":{"kind":"item","id":"T-022","title":"Suavizar profundidade do layout de campo 3D","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-022-suavizar-profundidade-campo-3d.md","itemType":"task"},"T-029":{"kind":"item","id":"T-029","title":"Lista de exercícios paginada (pastas lazy + pesquisa plana)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-029-lista-exercicios-paginacao-pastas-lazy.md","itemType":"task"},"T-030":{"kind":"item","id":"T-030","title":"Lista de exercícios — sem pasta primeiro, pastas por baixo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-030-lista-exercicios-sem-pasta-primeiro.md","itemType":"task"},"T-046":{"kind":"item","id":"T-046","title":"Lista horizontal — thumbnail a preencher a coluna sem espaços em branco","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-046-lista-horizontal-thumbnail-preencher.md","itemType":"task"},"T-047":{"kind":"item","id":"T-047","title":"Lista vertical — thumbnail a 100% do cartão sem cortes","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-047-lista-vertical-thumbnail-100.md","itemType":"task"},"T-048":{"kind":"item","id":"T-048","title":"Guardar exercício — media em background (imagem primeiro, depois vídeo e claro)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-048-guardar-exercicio-media-background.md","itemType":"task"},"T-051":{"kind":"item","id":"T-051","title":"Melhorias UI — badge Novo no marketplace, paginação no footer e labels lineup","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-051-melhorias-ui-lista-exercicios-marketplace-paginacao-lineup.md","itemType":"task"},"T-052":{"kind":"item","id":"T-052","title":"Contador de caracteres na descrição e materiais do exercício (aviso soft)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/items/T-052-contador-caracteres-descricao-materiais-aviso-soft.md","itemType":"task"},"S-001":{"kind":"story","id":"S-001","title":"Aumentar tamanho de texto e etiquetas dos elementos de exercício","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/story.md"},"T-001":{"kind":"item","id":"T-001","title":"Aumentar tamanho do elemento de texto para 180%","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-001-texto-elemento-180.md","itemType":"task"},"T-002":{"kind":"item","id":"T-002","title":"Aumentar tamanho das etiquetas inferiores para 180%","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-002-etiqueta-inferior-180.md","itemType":"task"},"T-028":{"kind":"item","id":"T-028","title":"Redimensionar tamanho do elemento de texto com slider","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-001-aumentar-tamanho-texto-etiquetas/items/T-028-redimensionar-texto-slider.md","itemType":"task"},"S-005":{"kind":"story","id":"S-005","title":"Unificar Categoria (exercícios) e Fase/Tipo (planeamento) com multi-selecção","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/story.md"},"T-032":{"kind":"item","id":"T-032","title":"Categorias exercícios/treinos — remover Esquemas tácticos e renomear labels","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-005-unificar-categoria-fase-tipo/items/T-032-categorias-renomear-remover-esquemas.md","itemType":"task"},"S-006":{"kind":"story","id":"S-006","title":"Duplicar exercício com confirmação e sufixo (copia)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/story.md"},"B-015":{"kind":"item","id":"B-015","title":"Duplicar exercício não regenera imagens/vídeos de preview","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/B-015-duplicar-exercicio-sem-imagens-videos-preview.md","itemType":"bug"},"T-049":{"kind":"item","id":"T-049","title":"Spinner de loading no botão duplicar exercício","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-001-motor-de-exercicios/stories/S-006-duplicar-exercicio/items/T-049-spinner-loading-duplicar-exercicio.md","itemType":"task"},"E-002":{"kind":"epic","id":"E-002","title":"PSE","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/epic.md"},"B-001":{"kind":"item","id":"B-001","title":"PSE salta para a primeira da semana após editar duração","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-001-pse-salta-para-primeira-apos-editar-duracao.md","itemType":"bug"},"B-007":{"kind":"item","id":"B-007","title":"Spam de emails PSE — cron reenvia sem onlyUnnotified e wipe de notifiedAt","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-007-spam-emails-pse-reenvio-cron.md","itemType":"bug"},"B-036":{"kind":"item","id":"B-036","title":"PSE — skeleton em loop numa semana sem treinos","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/B-036-pse-skeleton-loop-semana-sem-treinos.md","itemType":"bug"},"T-003":{"kind":"item","id":"T-003","title":"Selecção por defeito PSE — última da semana ou hoje","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-003-pse-selecao-defeito-ultima-ou-hoje.md","itemType":"task"},"T-006":{"kind":"item","id":"T-006","title":"Auto-gerar nome ao criar PSE no planeamento (treino/jogo)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/items/T-006-auto-gerar-nome-pse-planeamento.md","itemType":"task"},"S-003":{"kind":"story","id":"S-003","title":"Timeline de eventos no estado de envio de emails de notificação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-002-pse/stories/S-003-timeline-eventos-envio-email-notificacoes/story.md"},"E-003":{"kind":"epic","id":"E-003","title":"Wellness","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/epic.md"},"B-005":{"kind":"item","id":"B-005","title":"Spam de emails Wellness — cron reenvia apesar de estado Processado","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-005-spam-emails-wellness-reenvio-cron.md","itemType":"bug"},"B-010":{"kind":"item","id":"B-010","title":"Wellness manual no planeamento exige treino/jogo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/B-010-wellness-manual-planeamento-sem-sessao.md","itemType":"bug"},"T-007":{"kind":"item","id":"T-007","title":"Auto-gerar nome ao criar Wellness no planeamento (treino/jogo)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/items/T-007-auto-gerar-nome-wellness-planeamento.md","itemType":"task"},"S-004":{"kind":"story","id":"S-004","title":"Timeline de eventos no estado de envio de emails de notificação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-003-wellness/stories/S-004-timeline-eventos-envio-email-notificacoes/story.md"},"E-004":{"kind":"epic","id":"E-004","title":"Planeamento","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/epic.md"},"B-002":{"kind":"item","id":"B-002","title":"Sheet criar jogo no planeamento mostra i18n em inglês","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-002-sheet-criar-jogo-i18n-ingles.md","itemType":"bug"},"B-009":{"kind":"item","id":"B-009","title":"Export PDF semana omite jogos no domingo (filtro to date-only)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-009-export-pdf-semana-omite-jogos-domingo.md","itemType":"bug"},"B-013":{"kind":"item","id":"B-013","title":"Campo livre aparece em branco no relatório de unidade de treino","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-013-campo-livre-branco-relatorio-treino.md","itemType":"bug"},"B-023":{"kind":"item","id":"B-023","title":"Planeamento — tipo de jogo amigável não é gravado","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-023-tipo-jogo-amigavel-nao-gravado.md","itemType":"bug"},"B-024":{"kind":"item","id":"B-024","title":"Planeamento — MD-x em falta quando jogos estão a 7 dias","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/B-024-md-x-em-falta-jogos-a-7-dias.md","itemType":"bug"},"T-004":{"kind":"item","id":"T-004","title":"Reporte treino — text-gray-400 para text-gray-600","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-004-reporte-treino-text-gray-600.md","itemType":"task"},"T-005":{"kind":"item","id":"T-005","title":"Tab exercícios planeamento — ícone clipboard typography","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-005-tab-exercicios-icone-clipboard-typography.md","itemType":"task"},"T-020":{"kind":"item","id":"T-020","title":"Expanded layout — botão Voltar com hit target decente","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-020-expanded-layout-botao-voltar.md","itemType":"task"},"T-050":{"kind":"item","id":"T-050","title":"Código sequencial UT/TS nos treinos da época/equipa","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-050-codigo-sequencial-unidade-treino.md","itemType":"task"},"T-053":{"kind":"item","id":"T-053","title":"Intensidade do treino — níveis 1–10 e slider no formulário","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/items/T-053-intensidade-treino-niveis-slider-formulario.md","itemType":"task"},"S-007":{"kind":"story","id":"S-007","title":"Exportar calendário do planeamento em PDF (mensal e semana)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/story.md"},"B-029":{"kind":"item","id":"B-029","title":"Export semana — cabeçalhos desformatados quando MD-X só até meio da semana","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-007-exportar-calendario-pdf/items/B-029-export-semana-cabecalhos-desformatados-md-x.md","itemType":"bug"},"S-011":{"kind":"story","id":"S-011","title":"Mostrar meso e micro ciclos no calendário de planeamento","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-004-planeamento/stories/S-011-meso-micro-ciclos-calendario/story.md"},"E-005":{"kind":"epic","id":"E-005","title":"Lineup","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/epic.md"},"T-027":{"kind":"item","id":"T-027","title":"Exportar plantel — documento estilo relatório de unidade de treino","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-027-exportar-plantel-documento.md","itemType":"task"},"T-054":{"kind":"item","id":"T-054","title":"Jogador — campos Número e Pé preferencial (lista e export lineup)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-005-lineup/items/T-054-jogador-numero-pe-preferencial-lista-export.md","itemType":"task"},"E-006":{"kind":"epic","id":"E-006","title":"Website","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/epic.md"},"B-004":{"kind":"item","id":"B-004","title":"Artigos em destaque — imagem sem cover inflaciona os cartões","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/B-004-artigos-destaque-imagem-cover.md","itemType":"bug"},"T-008":{"kind":"item","id":"T-008","title":"Artigos website — restaurar bullets de listagem (disc)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-008-artigos-listagem-disc.md","itemType":"task"},"T-009":{"kind":"item","id":"T-009","title":"Artigos website — imagens a 100% da largura do conteúdo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-009-artigos-imagens-100-largura.md","itemType":"task"},"T-021":{"kind":"item","id":"T-021","title":"Hero — embed Loom com moldura responsiva","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-021-hero-loom-video.md","itemType":"task"},"T-057":{"kind":"item","id":"T-057","title":"Melhorar SEO do website e da app (titles, OG, robots, schema)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-006-website/items/T-057-melhorar-seo-site-e-app.md","itemType":"task"},"E-007":{"kind":"epic","id":"E-007","title":"Admin dashboard","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/epic.md"},"B-034":{"kind":"item","id":"B-034","title":"Resposta admin fecha ticket em vez de passar a Em progresso","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/items/B-034-resposta-admin-fecha-ticket-em-vez-de-em-progresso.md","itemType":"bug"},"S-008":{"kind":"story","id":"S-008","title":"CRUD de tags e categorias dos artigos do website no admin","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-008-crud-tags-categorias-artigos/story.md"},"S-009":{"kind":"story","id":"S-009","title":"Gerir autores de blog posts no admin (incluindo autores manuais)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/story.md"},"T-023":{"kind":"item","id":"T-023","title":"Port manual article author CRUD API to worktree-1","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-023-port-author-crud-worktree-1-api.md","itemType":"task"},"T-024":{"kind":"item","id":"T-024","title":"Admin sidebar submenu for article authors","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-024-admin-sidebar-article-authors.md","itemType":"task"},"T-025":{"kind":"item","id":"T-025","title":"Author photo file upload to S3","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-025-author-photo-s3-upload.md","itemType":"task"},"T-026":{"kind":"item","id":"T-026","title":"Authors table UI parity + text search","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-026-authors-table-ui-search.md","itemType":"task"},"T-031":{"kind":"item","id":"T-031","title":"Editar descrição do autor do blog (manual e utilizador) e mostrar no site","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-009-autores-blog-posts/items/T-031-editar-descricao-autor-blog.md","itemType":"task"},"S-010":{"kind":"story","id":"S-010","title":"Separar utilizadores e equipas em tabs e enriquecer a lista de utilizadores","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/story.md"},"T-013":{"kind":"item","id":"T-013","title":"Tabs Utilizadores / Equipas em /admin/users","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-013-tabs-utilizadores-equipas-admin-users.md","itemType":"task"},"T-014":{"kind":"item","id":"T-014","title":"Listagem de utilizadores com Criado em e Último acesso","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-014-listagem-utilizadores-criado-ultimo-acesso.md","itemType":"task"},"T-015":{"kind":"item","id":"T-015","title":"Coluna total de equipas com dialog de detalhe","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-015-coluna-equipas-dialog.md","itemType":"task"},"T-016":{"kind":"item","id":"T-016","title":"Coluna contas com acesso e dialog de subscrição","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-016-coluna-contas-dialog-subscricao.md","itemType":"task"},"T-017":{"kind":"item","id":"T-017","title":"Estado do utilizador calculado a partir das contas","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-017-estado-utilizador-derivado-contas.md","itemType":"task"},"T-018":{"kind":"item","id":"T-018","title":"Acções nos dialogs de equipas e contas do utilizador","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-018-accoes-dialogs-equipas-contas.md","itemType":"task"},"T-019":{"kind":"item","id":"T-019","title":"Coluna de métricas agregadas na lista de utilizadores","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-019-metricas-agregadas-utilizadores.md","itemType":"task"},"T-033":{"kind":"item","id":"T-033","title":"Modal subscrição admin — botão ver cliente no Stripe","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-033-modal-subscricao-botao-cliente-stripe.md","itemType":"task"},"T-041":{"kind":"item","id":"T-041","title":"Lista equipas admin — país sob o nome em vez do desporto","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-007-admin-dashboard/stories/S-010-lista-utilizadores-tabs-equipas/items/T-041-lista-equipas-admin-pais-em-vez-de-sport.md","itemType":"task"},"E-008":{"kind":"epic","id":"E-008","title":"Perfil de Utilizadores e Equipas","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/epic.md"},"B-003":{"kind":"item","id":"B-003","title":"Avatar no perfil não sincroniza no Auth0 (usar proxy frontend em vez de S3)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-003-avatar-auth0-proxy-frontend.md","itemType":"bug"},"B-025":{"kind":"item","id":"B-025","title":"Utilizadores duplicados na lista admin (mesmo auth0Sub)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-008-perfil-utilizadores-equipas/items/B-025-utilizadores-duplicados-lista-admin.md","itemType":"bug"},"E-009":{"kind":"epic","id":"E-009","title":"General","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/epic.md"},"B-006":{"kind":"item","id":"B-006","title":"Fotos dos jogadores não aparecem no PSE e Wellness (proxy frontend em vez de S3)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-006-fotos-jogadores-pse-wellness-proxy.md","itemType":"bug"},"B-008":{"kind":"item","id":"B-008","title":"Equipas duplicadas no setup/onboarding — retry e guard do wizard","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-008-equipas-duplicadas-setup-onboarding-wizard.md","itemType":"bug"},"B-014":{"kind":"item","id":"B-014","title":"Frontend build falha (zodResolver SeasonSettings) e avisos ESLint","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-014-frontend-build-zod-eslint.md","itemType":"bug"},"B-020":{"kind":"item","id":"B-020","title":"Picker de países — lista filtrada ao reabrir e bandeiras","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-020-picker-paises-filtro-bandeiras-combobox.md","itemType":"bug"},"B-021":{"kind":"item","id":"B-021","title":"Picker de países no modal de facturação — clique não selecciona","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-021-picker-paises-modal-facturacao-clique.md","itemType":"bug"},"B-028":{"kind":"item","id":"B-028","title":"Setup/wizard — país não pré-preenche ao escolher equipa do datacenter","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-028-setup-wizard-pais-nao-preenche-equipa-datacenter.md","itemType":"bug"},"B-030":{"kind":"item","id":"B-030","title":"Modal Completa o teu perfil aparece no setup/onboarding wizard","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/B-030-modal-completa-perfil-aparece-no-setup-wizard.md","itemType":"bug"},"T-010":{"kind":"item","id":"T-010","title":"Ícones PSE e Wellness na sidebar e no sumário da sessão","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-010-icones-pse-wellness-sidebar-sumario.md","itemType":"task"},"T-011":{"kind":"item","id":"T-011","title":"Ordenação SMTP — timestamp, prioridade lifecycle, depois reiceivedAt","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-011-ordenacao-smtp-timestamp-prioridade-reiceivedAt.md","itemType":"task"},"T-012":{"kind":"item","id":"T-012","title":"Timeline de envio — evento quando PSE/Wellness é respondido ou modificado","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-012-timeline-evento-resposta-modificacao-pse-wellness.md","itemType":"task"},"T-055":{"kind":"item","id":"T-055","title":"Open Graph — usar og.png como imagem Facebook no site e na app","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-055-open-graph-og-png-site-e-app.md","itemType":"task"},"T-056":{"kind":"item","id":"T-056","title":"Google Analytics — gtag na app e no site","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-056-google-analytics-app-e-site.md","itemType":"task"},"T-066":{"kind":"item","id":"T-066","title":"Script CLI para copiar equipa entre organizações","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/items/T-066-script-cli-copiar-equipa-entre-organizacoes.md","itemType":"task"},"S-017":{"kind":"story","id":"S-017","title":"Organizações próprias (sem Auth0 Orgs) — selector, migração, setup e páginas 401/404","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/story.md"},"B-031":{"kind":"item","id":"B-031","title":"Conta organizacional nova não fica em Trial (app)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-031-org-nova-sem-trial-app.md","itemType":"bug"},"B-032":{"kind":"item","id":"B-032","title":"Página de facturação em org abre Auth0 consent em vez da UI","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-032-facturacao-org-auth0-consent.md","itemType":"bug"},"B-037":{"kind":"item","id":"B-037","title":"Wizard — passo pessoal/org falta no registo e aparece ao criar equipa","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/B-037-wizard-passo-pessoal-org-registo-vs-nova-equipa.md","itemType":"bug"},"T-058":{"kind":"item","id":"T-058","title":"Entidade Organização, membership e API (sair das Auth0 Orgs)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-058-entidade-organizacao-membership-api.md","itemType":"task"},"T-059":{"kind":"item","id":"T-059","title":"Script de migração Auth0 Organizations → sistema próprio","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-059-script-migracao-auth0-orgs.md","itemType":"task"},"T-060":{"kind":"item","id":"T-060","title":"Selector de organização na sidebar (canto inferior esquerdo)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-060-selector-organizacao-sidebar.md","itemType":"task"},"T-061":{"kind":"item","id":"T-061","title":"Setup wizard — conta pessoal vs organizacional no 1º passo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-061-setup-wizard-pessoal-vs-organizacional.md","itemType":"task"},"T-062":{"kind":"item","id":"T-062","title":"Páginas 404 (botão início) e 401 (redirect login)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-009-general/stories/S-017-organizacoes-proprias-sem-auth0/items/T-062-paginas-404-e-401.md","itemType":"task"},"E-010":{"kind":"epic","id":"E-010","title":"Pagamentos","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/epic.md"},"S-012":{"kind":"story","id":"S-012","title":"Página de definições de facturação por conta (formulário + sync Stripe)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/story.md"},"B-017":{"kind":"item","id":"B-017","title":"Formulário de facturação — botão Guardar fica sempre desabilitado","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-017-formulario-facturacao-botao-guardar-desabilitado.md","itemType":"bug"},"B-018":{"kind":"item","id":"B-018","title":"Facturação — nome da empresa vs nome da conta no sync Stripe","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-018-facturacao-nome-empresa-sobrescreve-conta-stripe.md","itemType":"bug"},"B-033":{"kind":"item","id":"B-033","title":"Modal facturação — inputs Empresa mostram erro antes do submit","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/B-033-modal-facturacao-erros-antes-submit.md","itemType":"bug"},"T-035":{"kind":"item","id":"T-035","title":"Formulário facturação — toggle particular/empresa com campos condicionais","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-035-formulario-toggle-particular-empresa.md","itemType":"task"},"T-036":{"kind":"item","id":"T-036","title":"Facturação — campos opcionais para particular, obrigatórios para empresa","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-036-campos-opcionais-particular-obrigatorios-empresa.md","itemType":"task"},"T-037":{"kind":"item","id":"T-037","title":"Checkout — recolher dados de facturação antes do Stripe","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-037-checkout-requer-formulario-facturacao.md","itemType":"task"},"T-038":{"kind":"item","id":"T-038","title":"Pré-seleccionar país de facturação com o país da equipa","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-038-preseleccionar-pais-facturacao-da-equipa.md","itemType":"task"},"T-039":{"kind":"item","id":"T-039","title":"Modal dados de faturação — botão Cancelar","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-039-modal-facturacao-botao-cancelar.md","itemType":"task"},"T-040":{"kind":"item","id":"T-040","title":"Copy dos botões na página de facturação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-012-definicoes-facturacao-por-conta/items/T-040-copy-botoes-pagina-facturacao.md","itemType":"task"},"S-013":{"kind":"story","id":"S-013","title":"Dialog CTA quando subscrição activa sem dados de facturação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/story.md"},"B-019":{"kind":"item","id":"B-019","title":"Dialog de facturação aparece durante o setup da equipa","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-019-dialog-facturacao-aparece-durante-setup-equipa.md","itemType":"bug"},"B-035":{"kind":"item","id":"B-035","title":"Modal Completa faturação — botões colados sem margem","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-013-dialog-cta-facturacao-subscricao-activa/items/B-035-modal-completa-faturacao-botoes-colados.md","itemType":"bug"},"S-014":{"kind":"story","id":"S-014","title":"Listagem de facturas Stripe na página de facturação","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/story.md"},"T-034":{"kind":"item","id":"T-034","title":"Lista de facturas paginada (máx. 5 por página)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-010-pagamentos/stories/S-014-listagem-facturas-stripe/items/T-034-lista-facturas-paginada-5-por-pagina.md","itemType":"task"},"E-011":{"kind":"epic","id":"E-011","title":"Backup do produto","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/epic.md"},"T-064":{"kind":"item","id":"T-064","title":"Script para apagar wellness/RPE legacy do Mongo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/items/T-064-script-purge-legacy-wellness-rpe.md","itemType":"task"},"S-015":{"kind":"story","id":"S-015","title":"Backup automático diário Mongo → S3 (02:00)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/story.md"},"T-042":{"kind":"item","id":"T-042","title":"Pipeline mongodump → ZIP → upload S3","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-042-pipeline-mongodump-zip-upload-s3.md","itemType":"task"},"T-043":{"kind":"item","id":"T-043","title":"Agendar backup diário às 02:00","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-043-agendar-backup-diario-02h.md","itemType":"task"},"T-063":{"kind":"item","id":"T-063","title":"Nome do ZIP de backup a partir de APP_BASE_URL","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-015-backup-automatico-diario-mongo-s3/items/T-063-backup-filename-app-base-url.md","itemType":"task"},"S-016":{"kind":"story","id":"S-016","title":"CLI NPM para backup manual com inquirer","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/story.md"},"T-044":{"kind":"item","id":"T-044","title":"CLI npm + inquirer (host, user, password)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-044-cli-npm-inquirer-backup-mongo.md","itemType":"task"},"T-045":{"kind":"item","id":"T-045","title":"Documentar env vars e uso do backup","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-011-backup-produto/stories/S-016-cli-backup-manual-inquirer/items/T-045-documentar-backup-env-uso.md","itemType":"task"},"E-012":{"kind":"epic","id":"E-012","title":"Auth UI — login, registo e convites de organização","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/epic.md"},"S-018":{"kind":"story","id":"S-018","title":"Nova UI de login (shadcn login-02) com Auth0","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/story.md"},"B-038":{"kind":"item","id":"B-038","title":"Registo redirecciona para login Auth0 em vez do wizard","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-038-registo-redirect-auth0-login-em-vez-wizard.md","itemType":"bug"},"B-039":{"kind":"item","id":"B-039","title":"Confirmação de logout nativa (sem página Auth0)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-039-confirmacao-logout-nativa.md","itemType":"bug"},"B-040":{"kind":"item","id":"B-040","title":"Nunca usar logout Auth0 (só sessão local)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/B-040-nunca-usar-logout-auth0.md","itemType":"bug"},"T-067":{"kind":"item","id":"T-067","title":"Layout da página de login (shadcn login-02)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-067-layout-pagina-login-shadcn-login-02.md","itemType":"task"},"T-068":{"kind":"item","id":"T-068","title":"Ligar formulário de login ao Auth0","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-068-ligar-formulario-login-auth0.md","itemType":"task"},"T-078":{"kind":"item","id":"T-078","title":"Recuperar password no login (Auth0 change_password)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-078-recuperar-password-no-login.md","itemType":"task"},"T-079":{"kind":"item","id":"T-079","title":"Adaptar login e registo ao layout shadcn login-04","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-079-adaptar-login-registo-login-04.md","itemType":"task"},"T-081":{"kind":"item","id":"T-081","title":"Login e registo — loading com spinner nos botões","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-081-login-signup-button-spinners.md","itemType":"task"},"T-082":{"kind":"item","id":"T-082","title":"Logout — confirmação a página inteira sem cover","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-082-logout-sem-cover-imagem.md","itemType":"task"},"T-083":{"kind":"item","id":"T-083","title":"Auth light — logo cid_azul nas páginas login/logout/registo","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-018-ui-login-shadcn-login-02/items/T-083-auth-logo-light-cid-azul.md","itemType":"task"},"S-019":{"kind":"story","id":"S-019","title":"Nova UI de registo normal (shadcn signup-02) com Auth0","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/story.md"},"T-069":{"kind":"item","id":"T-069","title":"Layout da página de registo normal (shadcn signup-02)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-069-layout-pagina-registo-shadcn-signup-02.md","itemType":"task"},"T-070":{"kind":"item","id":"T-070","title":"Ligar formulário de registo normal ao Auth0","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-019-ui-registo-normal-shadcn-signup-02/items/T-070-ligar-formulario-registo-auth0.md","itemType":"task"},"S-020":{"kind":"story","id":"S-020","title":"Fluxo de convite para organização (email, registo, login e confirmação)","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/story.md"},"B-041":{"kind":"item","id":"B-041","title":"Registo por convite falha com “conta já existe”","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-041-registo-convite-conta-ja-existe.md","itemType":"bug"},"B-042":{"kind":"item","id":"B-042","title":"Email de convite sem assunto","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-042-email-convite-sem-assunto.md","itemType":"bug"},"B-043":{"kind":"item","id":"B-043","title":"Resend convite 404 na API main","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-043-resend-convite-404-api-main.md","itemType":"bug"},"B-044":{"kind":"item","id":"B-044","title":"Após registo por convite volta ao link inválido em vez do wizard","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-044-registo-convite-redirect-wizard.md","itemType":"bug"},"B-045":{"kind":"item","id":"B-045","title":"Resend convite 500 com id fake accepted-auth0","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-045-resend-convite-accepted-fake-id-500.md","itemType":"bug"},"B-046":{"kind":"item","id":"B-046","title":"Invite landing 500 ao setar cookie no RSC","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/B-046-invite-landing-cookie-rsc-500.md","itemType":"bug"},"T-071":{"kind":"item","id":"T-071","title":"Template SendGrid de convite à organização","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-071-template-sendgrid-convite-organizacao.md","itemType":"task"},"T-073":{"kind":"item","id":"T-073","title":"Rota landing de convite e resolução de estado","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-073-rota-landing-convite-resolver-estado.md","itemType":"task"},"T-074":{"kind":"item","id":"T-074","title":"Registo por convite — email readonly + contexto da org","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-074-registo-por-convite-email-readonly.md","itemType":"task"},"T-080":{"kind":"item","id":"T-080","title":"Registo por convite — password + confirmar password","filePath":"/Users/menda0/Projects/coachid/new/coachid-taskmark/epics/E-012-auth-ui-login-registo-convites/stories/S-020-fluxo-convite-organizacao-email-aceitacao/items/T-080-registo-convite-password-confirmar.md","itemType":"task"}}}