@taskmark/ui 0.2.6 → 0.3.1

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 (320) hide show
  1. package/README.md +16 -1
  2. package/app/board/page.tsx +3 -272
  3. package/app/globals.css +25 -0
  4. package/app/layout.tsx +15 -5
  5. package/app/page.tsx +14 -14
  6. package/app/setup/actions.ts +4 -4
  7. package/app/setup/page.tsx +9 -4
  8. package/bin/lib/resolve-board.mjs +1 -4
  9. package/bin/taskmark.js +15 -2
  10. package/components/board/app-bar.tsx +3 -0
  11. package/components/board/board-screen.tsx +229 -0
  12. package/components/board/changelog-panel.tsx +26 -0
  13. package/components/board/epic-list.tsx +4 -2
  14. package/components/board/list-view-switcher.tsx +7 -3
  15. package/components/board/markdown-content.tsx +21 -1
  16. package/components/board/mermaid-diagram.tsx +88 -0
  17. package/components/board/metric-stat-card.tsx +4 -4
  18. package/components/board/overall-tree-list.tsx +467 -0
  19. package/components/board/overall-work-items-list.tsx +6 -2
  20. package/components/board/points-heatmap.tsx +183 -0
  21. package/components/board/project-status-metrics-strip.tsx +5 -22
  22. package/components/board/static-board-app.tsx +29 -94
  23. package/components/board/status-badge.tsx +8 -0
  24. package/components/board/story-list.tsx +3 -1
  25. package/components/board/task-list.tsx +5 -1
  26. package/components/board/work-item-detail-body.tsx +123 -8
  27. package/components/board/work-items-list.tsx +2 -0
  28. package/components/theme-provider.tsx +39 -0
  29. package/components/theme-toggle.tsx +27 -0
  30. package/components/ui/sonner.tsx +2 -2
  31. package/dist/prod-next/BUILD_ID +1 -1
  32. package/dist/prod-next/app-path-routes-manifest.json +2 -2
  33. package/dist/prod-next/build-manifest.json +6 -6
  34. package/dist/prod-next/prerender-manifest.json +3 -27
  35. package/dist/prod-next/react-loadable-manifest.json +392 -2
  36. package/dist/prod-next/server/app/_global-error/page.js +2 -2
  37. package/dist/prod-next/server/app/_global-error/page.js.nft.json +1 -1
  38. package/dist/prod-next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  39. package/dist/prod-next/server/app/_global-error.html +1 -1
  40. package/dist/prod-next/server/app/_global-error.rsc +1 -1
  41. package/dist/prod-next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  42. package/dist/prod-next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  43. package/dist/prod-next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  44. package/dist/prod-next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  45. package/dist/prod-next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  46. package/dist/prod-next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  47. package/dist/prod-next/server/app/_not-found/page.js +2 -2
  48. package/dist/prod-next/server/app/_not-found/page.js.nft.json +1 -1
  49. package/dist/prod-next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  50. package/dist/prod-next/server/app/_not-found.html +1 -1
  51. package/dist/prod-next/server/app/_not-found.rsc +19 -17
  52. package/dist/prod-next/server/app/_not-found.segments/_full.segment.rsc +19 -17
  53. package/dist/prod-next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  54. package/dist/prod-next/server/app/_not-found.segments/_index.segment.rsc +8 -6
  55. package/dist/prod-next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  56. package/dist/prod-next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  57. package/dist/prod-next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  58. package/dist/prod-next/server/app/api/taskmark-reload/route.js +1 -1
  59. package/dist/prod-next/server/app/api/taskmark-reload/route.js.nft.json +1 -1
  60. package/dist/prod-next/server/app/board/page.js +2 -50
  61. package/dist/prod-next/server/app/board/page.js.nft.json +1 -1
  62. package/dist/prod-next/server/app/board/page_client-reference-manifest.js +1 -1
  63. package/dist/prod-next/server/app/favicon.ico/route.js +1 -1
  64. package/dist/prod-next/server/app/favicon.ico/route.js.nft.json +1 -1
  65. package/dist/prod-next/server/app/page.js +2 -2
  66. package/dist/prod-next/server/app/page.js.nft.json +1 -1
  67. package/dist/prod-next/server/app/page_client-reference-manifest.js +1 -1
  68. package/dist/prod-next/server/app/setup/page.js +2 -2
  69. package/dist/prod-next/server/app/setup/page.js.nft.json +1 -1
  70. package/dist/prod-next/server/app/setup/page_client-reference-manifest.js +1 -1
  71. package/dist/prod-next/server/app-paths-manifest.json +2 -2
  72. package/dist/prod-next/server/chunks/102.js +90 -0
  73. package/dist/prod-next/server/chunks/11.js +1 -0
  74. package/dist/prod-next/server/chunks/1286.js +1 -0
  75. package/dist/prod-next/server/chunks/1412.js +38 -0
  76. package/dist/prod-next/server/chunks/1605.js +1 -0
  77. package/dist/prod-next/server/chunks/169.js +1 -0
  78. package/dist/prod-next/server/chunks/18.js +86 -0
  79. package/dist/prod-next/server/chunks/2.js +1 -0
  80. package/dist/prod-next/server/chunks/2022.js +1 -0
  81. package/dist/prod-next/server/chunks/2156.js +1 -0
  82. package/dist/prod-next/server/chunks/2157.js +1 -0
  83. package/dist/prod-next/server/chunks/2325.js +82 -0
  84. package/dist/prod-next/server/chunks/2838.js +1 -0
  85. package/dist/prod-next/server/chunks/2897.js +79 -0
  86. package/dist/prod-next/server/chunks/3227.js +1 -0
  87. package/dist/prod-next/server/chunks/3266.js +1 -0
  88. package/dist/prod-next/server/chunks/3307.js +49 -0
  89. package/dist/prod-next/server/chunks/3387.js +19 -0
  90. package/dist/prod-next/server/chunks/3428.js +32 -0
  91. package/dist/prod-next/server/chunks/3479.js +1 -0
  92. package/dist/prod-next/server/chunks/367.js +115 -0
  93. package/dist/prod-next/server/chunks/3698.js +93 -0
  94. package/dist/prod-next/server/chunks/3709.js +148 -0
  95. package/dist/prod-next/server/chunks/41.js +1 -0
  96. package/dist/prod-next/server/chunks/4107.js +62 -0
  97. package/dist/prod-next/server/chunks/4569.js +34 -0
  98. package/dist/prod-next/server/chunks/{741.js → 4741.js} +1 -1
  99. package/dist/prod-next/server/chunks/4755.js +153 -0
  100. package/dist/prod-next/server/chunks/487.js +1 -0
  101. package/dist/prod-next/server/chunks/5002.js +1 -0
  102. package/dist/prod-next/server/chunks/5112.js +1 -0
  103. package/dist/prod-next/server/chunks/5289.js +8 -0
  104. package/dist/prod-next/server/chunks/5318.js +1 -0
  105. package/dist/prod-next/server/chunks/5452.js +23 -0
  106. package/dist/prod-next/server/chunks/5453.js +1 -0
  107. package/dist/prod-next/server/chunks/5749.js +27 -0
  108. package/dist/prod-next/server/chunks/5782.js +36 -0
  109. package/dist/prod-next/server/chunks/6163.js +104 -0
  110. package/dist/prod-next/server/chunks/6169.js +64 -0
  111. package/dist/prod-next/server/chunks/6208.js +172 -0
  112. package/dist/prod-next/server/chunks/6399.js +24 -0
  113. package/dist/prod-next/server/chunks/6496.js +1 -0
  114. package/dist/prod-next/server/chunks/6823.js +215 -0
  115. package/dist/prod-next/server/chunks/6888.js +1 -0
  116. package/dist/prod-next/server/chunks/6980.js +1 -0
  117. package/dist/prod-next/server/chunks/7245.js +77 -0
  118. package/dist/prod-next/server/chunks/7307.js +1 -0
  119. package/dist/prod-next/server/chunks/7372.js +287 -0
  120. package/dist/prod-next/server/chunks/7384.js +226 -0
  121. package/dist/prod-next/server/chunks/7516.js +1 -0
  122. package/dist/prod-next/server/chunks/7531.js +24 -0
  123. package/dist/prod-next/server/chunks/7591.js +1 -0
  124. package/dist/prod-next/server/chunks/7755.js +138 -0
  125. package/dist/prod-next/server/chunks/7916.js +1 -0
  126. package/dist/prod-next/server/chunks/8078.js +94 -0
  127. package/dist/prod-next/server/chunks/8253.js +41 -0
  128. package/dist/prod-next/server/chunks/8635.js +1 -0
  129. package/dist/prod-next/server/chunks/8688.js +1 -0
  130. package/dist/prod-next/server/chunks/8872.js +1 -0
  131. package/dist/prod-next/server/chunks/9006.js +1 -0
  132. package/dist/prod-next/server/chunks/9018.js +1 -0
  133. package/dist/prod-next/server/chunks/9047.js +1 -0
  134. package/dist/prod-next/server/chunks/9108.js +1 -0
  135. package/dist/prod-next/server/chunks/9280.js +256 -0
  136. package/dist/prod-next/server/chunks/9419.js +1 -0
  137. package/dist/prod-next/server/chunks/9430.js +1 -0
  138. package/dist/prod-next/server/chunks/9586.js +1 -0
  139. package/dist/prod-next/server/chunks/9775.js +1 -0
  140. package/dist/prod-next/server/chunks/992.js +1 -0
  141. package/dist/prod-next/server/chunks/9926.js +1 -0
  142. package/dist/prod-next/server/chunks/9984.js +8 -0
  143. package/dist/prod-next/server/middleware-build-manifest.js +1 -1
  144. package/dist/prod-next/server/middleware-react-loadable-manifest.js +1 -1
  145. package/dist/prod-next/server/pages/404.html +1 -1
  146. package/dist/prod-next/server/pages/500.html +1 -1
  147. package/dist/prod-next/server/server-reference-manifest.js +1 -1
  148. package/dist/prod-next/server/server-reference-manifest.json +1 -1
  149. package/dist/prod-next/server/webpack-runtime.js +1 -1
  150. package/dist/prod-next/static/chunks/1213.e5c6e70a79b5f7e6.js +24 -0
  151. package/dist/prod-next/static/chunks/1519.2f596e5f5af9ef57.js +62 -0
  152. package/dist/prod-next/static/chunks/1759-f5b8fb456f8fb420.js +1 -0
  153. package/dist/prod-next/static/chunks/1974.885c9a133b86d8a4.js +32 -0
  154. package/dist/prod-next/static/chunks/2280.6a7f540787704698.js +1 -0
  155. package/dist/prod-next/static/chunks/2521.7f745f50d30076e7.js +77 -0
  156. package/dist/prod-next/static/chunks/2585.4d6aa847c780c666.js +1 -0
  157. package/dist/prod-next/static/chunks/2589.1aad68c09021b1ac.js +1 -0
  158. package/dist/prod-next/static/chunks/2600.45ba17a0f756fc31.js +1 -0
  159. package/dist/prod-next/static/chunks/2619.9aac8983f30c7c8a.js +1 -0
  160. package/dist/prod-next/static/chunks/26d302b2.9f6383e42abdfe16.js +122 -0
  161. package/dist/prod-next/static/chunks/2768.305914f7900745b6.js +1 -0
  162. package/dist/prod-next/static/chunks/2931.c2acdbf72808b646.js +41 -0
  163. package/dist/prod-next/static/chunks/3012-838f69b72a0dc1b3.js +1 -0
  164. package/dist/prod-next/static/chunks/3016.406e568aa95ff867.js +1 -0
  165. package/dist/prod-next/static/chunks/3022.972047558a20553a.js +172 -0
  166. package/dist/prod-next/static/chunks/3064.3a2a1e7cd4fdca5f.js +1 -0
  167. package/dist/prod-next/static/chunks/3174.03fbed7b7d7a8256.js +1 -0
  168. package/dist/prod-next/static/chunks/3189.b048866768087750.js +1 -0
  169. package/dist/prod-next/static/chunks/3217.1a053843c58b70b5.js +24 -0
  170. package/dist/prod-next/static/chunks/3308.30b95d524f9c1daf.js +74 -0
  171. package/dist/prod-next/static/chunks/331.fc5d78e1e91daf43.js +1 -0
  172. package/dist/prod-next/static/chunks/3510.5d4d1c79533e080c.js +1 -0
  173. package/dist/prod-next/static/chunks/364.ce5400a9dd70b9dc.js +1 -0
  174. package/dist/prod-next/static/chunks/3661-1f08d73aaffb011d.js +1 -0
  175. package/dist/prod-next/static/chunks/370.57cfa27da8567918.js +1 -0
  176. package/dist/prod-next/static/chunks/3789.c418b69121761983.js +1 -0
  177. package/dist/prod-next/static/chunks/3794-c66b3d8325973459.js +32 -0
  178. package/dist/prod-next/static/chunks/3831.25ae62d10dccc27a.js +1 -0
  179. package/dist/prod-next/static/chunks/395.b41e9d76613d37b5.js +90 -0
  180. package/dist/prod-next/static/chunks/3a7aa434.93dbd20997cfd24f.js +82 -0
  181. package/dist/prod-next/static/chunks/4020.3cc19c463c49f969.js +23 -0
  182. package/dist/prod-next/static/chunks/4035.0acc428926d5c8dd.js +1 -0
  183. package/dist/prod-next/static/chunks/405.0902e4f6eb7bd9a2.js +215 -0
  184. package/dist/prod-next/static/chunks/4159.49ae537ff687bdc6.js +138 -0
  185. package/dist/prod-next/static/chunks/4208.384b381ca2757643.js +287 -0
  186. package/dist/prod-next/static/chunks/4263.ffa8d9bd8a0faaae.js +1 -0
  187. package/dist/prod-next/static/chunks/4561.d1a3aaca8bae3224.js +34 -0
  188. package/dist/prod-next/static/chunks/4592.d0f37bc216b9d988.js +93 -0
  189. package/dist/prod-next/static/chunks/4799.0dc7aa21bff2fd2a.js +1 -0
  190. package/dist/prod-next/static/chunks/4bd1b696-e356ca5ba0218e27.js +1 -0
  191. package/dist/prod-next/static/chunks/514.b804c51b26f5e126.js +1 -0
  192. package/dist/prod-next/static/chunks/5270.28592864d38e881c.js +1 -0
  193. package/dist/prod-next/static/chunks/52733464.3870f99cc446f9ff.js +1 -0
  194. package/dist/prod-next/static/chunks/5354.b559c717a607dc5c.js +1 -0
  195. package/dist/prod-next/static/chunks/5448.d3972d9fb464b54f.js +38 -0
  196. package/dist/prod-next/static/chunks/587.d52737d7288c11b4.js +1 -0
  197. package/dist/prod-next/static/chunks/5909.9e37f7b495b11995.js +115 -0
  198. package/dist/prod-next/static/chunks/5949.5504b3545fcc3d34.js +104 -0
  199. package/dist/prod-next/static/chunks/6322-4e97920c006f7933.js +1 -0
  200. package/dist/prod-next/static/chunks/6361.893d04ac34fa1b49.js +148 -0
  201. package/dist/prod-next/static/chunks/6774.8cd53427dbf32cac.js +86 -0
  202. package/dist/prod-next/static/chunks/6968.b80277c724dbc96e.js +1 -0
  203. package/dist/prod-next/static/chunks/7113.4b9e7ea870aa300a.js +8 -0
  204. package/dist/prod-next/static/chunks/7236.55a9728d35f5b8a6.js +1 -0
  205. package/dist/prod-next/static/chunks/7390.dde9b5bc2f6e24b8.js +1 -0
  206. package/dist/prod-next/static/chunks/7806.a903780fcfa3a30e.js +1 -0
  207. package/dist/prod-next/static/chunks/7997.be57e92e583fe635.js +1 -0
  208. package/dist/prod-next/static/chunks/8216.64a72d4d35ea7be0.js +1 -0
  209. package/dist/prod-next/static/chunks/830.5d5274d7ad1cb58e.js +1 -0
  210. package/dist/prod-next/static/chunks/8378.fa91de3406f554c9.js +226 -0
  211. package/dist/prod-next/static/chunks/8501.cd06aa1b0c7e1c6a.js +79 -0
  212. package/dist/prod-next/static/chunks/8663.6ec5792fb4952e45.js +27 -0
  213. package/dist/prod-next/static/chunks/872.96937e758ddce860.js +1 -0
  214. package/dist/prod-next/static/chunks/8803.75bde095fe3613f5.js +1 -0
  215. package/dist/prod-next/static/chunks/8863.72f5dbb820a0e4c3.js +1 -0
  216. package/dist/prod-next/static/chunks/90542734.f7a7b2972ef5a749.js +1 -0
  217. package/dist/prod-next/static/chunks/9379.5bc9c9343ec5a16c.js +64 -0
  218. package/dist/prod-next/static/chunks/9389.906fe7aa9cd6a170.js +1 -0
  219. package/dist/prod-next/static/chunks/9472.8818ee52cfa931a4.js +94 -0
  220. package/dist/prod-next/static/chunks/966.d6babbf8119162cc.js +1 -0
  221. package/dist/prod-next/static/chunks/9884.d4ac1a961b3366f1.js +36 -0
  222. package/dist/prod-next/static/chunks/9909.67cf9940b125243b.js +1 -0
  223. package/dist/prod-next/static/chunks/app/_global-error/page-8be5492b3b872a4c.js +1 -0
  224. package/dist/prod-next/static/chunks/app/_not-found/page-799e445a538b0024.js +1 -0
  225. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-8be5492b3b872a4c.js +1 -0
  226. package/dist/prod-next/static/chunks/app/board/page-5c181f45738daf1c.js +1 -0
  227. package/dist/prod-next/static/chunks/app/layout-21782e6d13a6f275.js +1 -0
  228. package/dist/prod-next/static/chunks/app/page-51bfe4356fe233e3.js +1 -0
  229. package/dist/prod-next/static/chunks/app/setup/page-3ccfba00c10f9b17.js +1 -0
  230. package/dist/prod-next/static/chunks/d3ac728e.7964f816a1ca64e5.js +1 -0
  231. package/dist/prod-next/static/chunks/e413bedd.3a12a8cb02e28fdf.js +153 -0
  232. package/dist/prod-next/static/chunks/ea233666.f00b64a7d99b4950.js +62 -0
  233. package/dist/prod-next/static/chunks/framework-711ef29bc66f648c.js +1 -0
  234. package/dist/prod-next/static/chunks/main-app-dd26d4f9d120646e.js +1 -0
  235. package/dist/prod-next/static/chunks/{main-bb33c46a9c25dee8.js → main-df4bcaed74f274eb.js} +2 -2
  236. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-8be5492b3b872a4c.js +1 -0
  237. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-8be5492b3b872a4c.js +1 -0
  238. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/global-error-45a0cf77e03361ed.js +1 -0
  239. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-8be5492b3b872a4c.js +1 -0
  240. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-8be5492b3b872a4c.js +1 -0
  241. package/dist/prod-next/static/chunks/webpack-713747aaa9716c4c.js +1 -0
  242. package/dist/prod-next/static/css/cb78d4b0062d9a3f.css +1 -0
  243. package/dist/public/taskmark-snapshot.json +1 -1
  244. package/lib/taskmark/board-index.ts +101 -0
  245. package/lib/taskmark/build-snapshot.ts +28 -7
  246. package/lib/taskmark/derive-parents.test.ts +23 -0
  247. package/lib/taskmark/derive-parents.ts +323 -0
  248. package/lib/taskmark/detail-load.ts +55 -7
  249. package/lib/taskmark/detail-types.ts +10 -2
  250. package/lib/taskmark/dev-reload-token.ts +1 -1
  251. package/lib/taskmark/discover.ts +4 -7
  252. package/lib/taskmark/epic-types.ts +2 -1
  253. package/lib/taskmark/flat-work-item-types.ts +1 -4
  254. package/lib/taskmark/identity.ts +3 -3
  255. package/lib/taskmark/item-types.ts +2 -1
  256. package/lib/taskmark/list-filters.test.ts +23 -0
  257. package/lib/taskmark/list-filters.ts +7 -2
  258. package/lib/taskmark/list-view-mode.test.ts +45 -0
  259. package/lib/taskmark/list-view-mode.ts +20 -9
  260. package/lib/taskmark/load-changelog.test.ts +32 -0
  261. package/lib/taskmark/load-changelog.ts +18 -0
  262. package/lib/taskmark/overall-tree.test.ts +196 -0
  263. package/lib/taskmark/overall-tree.ts +194 -0
  264. package/lib/taskmark/parse-detail.ts +5 -5
  265. package/lib/taskmark/parse-epics.ts +19 -16
  266. package/lib/taskmark/parse-flat-lists.ts +32 -28
  267. package/lib/taskmark/parse-items.ts +47 -9
  268. package/lib/taskmark/parse-stories.ts +18 -15
  269. package/lib/taskmark/points-calendar.test.ts +72 -0
  270. package/lib/taskmark/points-calendar.ts +86 -0
  271. package/lib/taskmark/project-metrics.ts +11 -7
  272. package/lib/taskmark/snapshot-types.ts +2 -0
  273. package/lib/taskmark/story-types.ts +2 -1
  274. package/lib/taskmark/table-sort.ts +4 -3
  275. package/lib/taskmark/timing.ts +29 -18
  276. package/lib/taskmark/validate.ts +1 -1
  277. package/lib/theme-cookie.test.ts +27 -0
  278. package/lib/theme-cookie.ts +43 -0
  279. package/package.json +3 -1
  280. package/public/taskmark-snapshot.json +1 -1
  281. package/scripts/build-static.mjs +61 -3
  282. package/dist/prod-next/server/app/setup.html +0 -1
  283. package/dist/prod-next/server/app/setup.meta +0 -17
  284. package/dist/prod-next/server/app/setup.rsc +0 -22
  285. package/dist/prod-next/server/app/setup.segments/_full.segment.rsc +0 -22
  286. package/dist/prod-next/server/app/setup.segments/_head.segment.rsc +0 -6
  287. package/dist/prod-next/server/app/setup.segments/_index.segment.rsc +0 -8
  288. package/dist/prod-next/server/app/setup.segments/_tree.segment.rsc +0 -5
  289. package/dist/prod-next/server/app/setup.segments/setup/__PAGE__.segment.rsc +0 -6
  290. package/dist/prod-next/server/app/setup.segments/setup.segment.rsc +0 -5
  291. package/dist/prod-next/server/chunks/318.js +0 -1
  292. package/dist/prod-next/server/chunks/490.js +0 -8
  293. package/dist/prod-next/server/chunks/57.js +0 -19
  294. package/dist/prod-next/server/chunks/616.js +0 -1
  295. package/dist/prod-next/server/chunks/708.js +0 -1
  296. package/dist/prod-next/server/chunks/724.js +0 -1
  297. package/dist/prod-next/static/chunks/4bd1b696-deb4a0a1da1923b0.js +0 -1
  298. package/dist/prod-next/static/chunks/51.e9139a9ea6eb36b9.js +0 -1
  299. package/dist/prod-next/static/chunks/613-6f794154d28bb75a.js +0 -1
  300. package/dist/prod-next/static/chunks/669-8103441c67b185da.js +0 -1
  301. package/dist/prod-next/static/chunks/701-df3ee5f1cf837b1a.js +0 -1
  302. package/dist/prod-next/static/chunks/794-25668765560cb197.js +0 -32
  303. package/dist/prod-next/static/chunks/app/_global-error/page-d34451c04262dd7d.js +0 -1
  304. package/dist/prod-next/static/chunks/app/_not-found/page-0b3785af737e7968.js +0 -1
  305. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-d34451c04262dd7d.js +0 -1
  306. package/dist/prod-next/static/chunks/app/board/page-cd1d9be0c0127225.js +0 -1
  307. package/dist/prod-next/static/chunks/app/layout-856e8a282e69e7d0.js +0 -1
  308. package/dist/prod-next/static/chunks/app/page-d34451c04262dd7d.js +0 -1
  309. package/dist/prod-next/static/chunks/app/setup/page-c3003359e8becc84.js +0 -1
  310. package/dist/prod-next/static/chunks/framework-b29f9083d3cda3b2.js +0 -1
  311. package/dist/prod-next/static/chunks/main-app-bfb36455d24b3e5a.js +0 -1
  312. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-d34451c04262dd7d.js +0 -1
  313. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-d34451c04262dd7d.js +0 -1
  314. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/global-error-dc53ab29e0491fe4.js +0 -1
  315. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-d34451c04262dd7d.js +0 -1
  316. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-d34451c04262dd7d.js +0 -1
  317. package/dist/prod-next/static/chunks/webpack-bfe8992962004e2b.js +0 -1
  318. package/dist/prod-next/static/css/2e6ec4c80894e3c0.css +0 -1
  319. /package/dist/prod-next/static/{sAWr5ATVuqk6Wqs18kAWs → EI1zQaa_kQ7DqUSE4o3Qo}/_buildManifest.js +0 -0
  320. /package/dist/prod-next/static/{sAWr5ATVuqk6Wqs18kAWs → EI1zQaa_kQ7DqUSE4o3Qo}/_ssgManifest.js +0 -0
@@ -0,0 +1,194 @@
1
+ import type { ContributorIdentity } from "@/lib/taskmark/identity"
2
+ import type { EpicSummary, ProjectEpicList } from "@/lib/taskmark/epic-types"
3
+ import type {
4
+ EpicWorkItemsList,
5
+ WorkItemsViewRow,
6
+ } from "@/lib/taskmark/flat-work-item-types"
7
+ import type { ItemSummary, StoryItemList } from "@/lib/taskmark/item-types"
8
+ import { isGeneralEpic } from "@/lib/taskmark/general-epic"
9
+ import {
10
+ matchesWorkItemSearch,
11
+ type TimeframeFilterState,
12
+ } from "@/lib/taskmark/list-filters"
13
+ import { passesTimeframeFilter } from "@/lib/taskmark/timeframe-filters"
14
+
15
+ export type OverallTreeNode = {
16
+ kind: "epic" | "story" | "task" | "bug"
17
+ id: string
18
+ title: string
19
+ status: string
20
+ size: string
21
+ points: number | null
22
+ tags: string[]
23
+ reporters: ContributorIdentity[]
24
+ resolvers: ContributorIdentity[]
25
+ created: string
26
+ updated: string
27
+ completedAt: string
28
+ filePath: string
29
+ children: OverallTreeNode[]
30
+ workItemCount: number
31
+ doneWorkItemCount: number
32
+ }
33
+
34
+ export function isOverallNodeComplete(status: string): boolean {
35
+ const normalized = status.trim().toLowerCase()
36
+ return (
37
+ normalized === "done" ||
38
+ normalized === "shelved" ||
39
+ normalized === "cancelled"
40
+ )
41
+ }
42
+
43
+ function timestamp(value: string): number {
44
+ const parsed = Date.parse(value)
45
+ return Number.isFinite(parsed) ? parsed : 0
46
+ }
47
+
48
+ /** Incomplete first, then created/updated newest-first, then id. */
49
+ export function compareOverallNodes(
50
+ a: Pick<OverallTreeNode, "status" | "created" | "updated" | "id">,
51
+ b: Pick<OverallTreeNode, "status" | "created" | "updated" | "id">
52
+ ): number {
53
+ const completion = Number(isOverallNodeComplete(a.status)) -
54
+ Number(isOverallNodeComplete(b.status))
55
+ if (completion !== 0) return completion
56
+ const created = timestamp(b.created) - timestamp(a.created)
57
+ if (created !== 0) return created
58
+ const updated = timestamp(b.updated) - timestamp(a.updated)
59
+ if (updated !== 0) return updated
60
+ return a.id.localeCompare(b.id)
61
+ }
62
+
63
+ function itemNode(item: ItemSummary): OverallTreeNode {
64
+ return {
65
+ kind: item.type,
66
+ id: item.id,
67
+ title: item.title,
68
+ status: item.status,
69
+ size: item.size,
70
+ points: item.points,
71
+ tags: item.tags,
72
+ reporters: item.reporters,
73
+ resolvers: item.resolvers,
74
+ created: item.created,
75
+ updated: item.updated,
76
+ completedAt: item.completedAt,
77
+ filePath: item.filePath,
78
+ children: [],
79
+ workItemCount: 0,
80
+ doneWorkItemCount: 0,
81
+ }
82
+ }
83
+
84
+ function workItemNode(
85
+ row: WorkItemsViewRow,
86
+ storyItems: StoryItemList | undefined
87
+ ): OverallTreeNode {
88
+ const children =
89
+ row.kind === "story"
90
+ ? (storyItems?.items ?? []).map(itemNode).sort(compareOverallNodes)
91
+ : []
92
+ return {
93
+ kind: row.kind,
94
+ id: row.id,
95
+ title: row.title,
96
+ status: row.status,
97
+ size: row.size,
98
+ points: row.points,
99
+ tags: row.tags,
100
+ reporters: row.reporters,
101
+ resolvers: row.resolvers,
102
+ created: row.created,
103
+ updated: row.updated,
104
+ completedAt: row.completedAt,
105
+ filePath: row.filePath,
106
+ children,
107
+ workItemCount: row.workItemCount,
108
+ doneWorkItemCount: row.doneWorkItemCount,
109
+ }
110
+ }
111
+
112
+ function epicNode(
113
+ epic: EpicSummary,
114
+ workItems: EpicWorkItemsList | undefined,
115
+ itemsByStory: Record<string, StoryItemList>
116
+ ): OverallTreeNode {
117
+ const children = (workItems?.rows ?? [])
118
+ .map((row) => workItemNode(row, itemsByStory[`${epic.id}::${row.id}`]))
119
+ .sort(compareOverallNodes)
120
+ return {
121
+ kind: "epic",
122
+ id: epic.id,
123
+ title: epic.title,
124
+ status: epic.status,
125
+ size: epic.size,
126
+ points: epic.points,
127
+ tags: epic.tags,
128
+ reporters: epic.reporters,
129
+ resolvers: epic.resolvers,
130
+ created: epic.created,
131
+ updated: epic.updated,
132
+ completedAt: epic.completedAt,
133
+ filePath: epic.filePath,
134
+ children,
135
+ workItemCount: epic.workItemCount,
136
+ doneWorkItemCount: epic.doneWorkItemCount,
137
+ }
138
+ }
139
+
140
+ export function buildOverallTree(
141
+ epicList: ProjectEpicList,
142
+ workItemsByEpic: Record<string, EpicWorkItemsList>,
143
+ itemsByStory: Record<string, StoryItemList>
144
+ ): OverallTreeNode[] {
145
+ return epicList.epics
146
+ .filter((epic) => !(isGeneralEpic(epic) && epic.workItemCount === 0))
147
+ .map((epic) => epicNode(epic, workItemsByEpic[epic.id], itemsByStory))
148
+ .sort(compareOverallNodes)
149
+ }
150
+
151
+ export type OverallTreeFilters = {
152
+ query: string
153
+ hideCompleted: boolean
154
+ timeframe: TimeframeFilterState
155
+ }
156
+
157
+ /**
158
+ * Retain a node when it matches itself or has a matching descendant. This
159
+ * preserves hierarchy context for search, completed filtering, and timeframe.
160
+ */
161
+ export function filterOverallTree(
162
+ nodes: readonly OverallTreeNode[],
163
+ filters: OverallTreeFilters
164
+ ): OverallTreeNode[] {
165
+ return nodes.flatMap((node) => {
166
+ const children = filterOverallTree(node.children, filters)
167
+ const selfMatches =
168
+ matchesWorkItemSearch(filters.query, node) &&
169
+ (!filters.hideCompleted || !isOverallNodeComplete(node.status)) &&
170
+ passesTimeframeFilter(filters.timeframe, node.completedAt)
171
+ if (!selfMatches && children.length === 0) return []
172
+ return [{ ...node, children }]
173
+ })
174
+ }
175
+
176
+ export function collectExpandableAncestorIds(
177
+ nodes: readonly OverallTreeNode[]
178
+ ): string[] {
179
+ return nodes.flatMap((node) => [
180
+ ...(node.children.length > 0 ? [node.id] : []),
181
+ ...collectExpandableAncestorIds(node.children),
182
+ ])
183
+ }
184
+
185
+ /**
186
+ * Only a search reveals matches by expanding their ancestors. Toggle filters
187
+ * such as hide-completed and timeframe keep whatever the user has open.
188
+ */
189
+ export function searchRevealIds(
190
+ nodes: readonly OverallTreeNode[],
191
+ query: string
192
+ ): string[] {
193
+ return query.trim() ? collectExpandableAncestorIds(nodes) : []
194
+ }
@@ -5,7 +5,7 @@ import {
5
5
  extractFrontmatter,
6
6
  } from "@/lib/taskmark/frontmatter"
7
7
  import { asContributorList } from "@/lib/taskmark/identity"
8
- import { readTimingFields } from "@/lib/taskmark/timing"
8
+ import { readActualTimingFromWorkLog } from "@/lib/taskmark/timing"
9
9
  import type {
10
10
  CommitRow,
11
11
  EpicDetail,
@@ -85,6 +85,7 @@ function resolveKind(
85
85
 
86
86
  function buildMeta(
87
87
  frontmatter: Record<string, unknown>,
88
+ raw: string,
88
89
  filePath: string,
89
90
  kind: WorkItemKind
90
91
  ): WorkItemMeta | null {
@@ -92,7 +93,7 @@ function buildMeta(
92
93
  const title = asString(frontmatter.title)
93
94
  if (!id || !title) return null
94
95
 
95
- const timing = readTimingFields(frontmatter)
96
+ const timing = readActualTimingFromWorkLog(raw)
96
97
  return {
97
98
  id,
98
99
  title,
@@ -101,11 +102,9 @@ function buildMeta(
101
102
  priority: asString(frontmatter.priority, "medium"),
102
103
  size: asString(frontmatter.size, "—"),
103
104
  points: asNumberOrNull(frontmatter.points),
104
- estimateMinutes: timing.estimateMinutes,
105
105
  actualMinutes: timing.actualMinutes,
106
106
  actualMs: timing.actualMs,
107
107
  tags: asStringArray(frontmatter.tags),
108
- owner: asString(frontmatter.owner),
109
108
  reporters: asContributorList(frontmatter.reporters),
110
109
  resolvers: asContributorList(frontmatter.resolvers),
111
110
  blocked: asBool(frontmatter.blocked),
@@ -147,7 +146,7 @@ export function parseWorkItemDetailFromRaw(
147
146
 
148
147
  const id = asString(frontmatter.id)
149
148
  const kind = resolveKind(frontmatter, id, hint)
150
- const meta = buildMeta(frontmatter, filePath, kind)
149
+ const meta = buildMeta(frontmatter, raw, filePath, kind)
151
150
  if (!meta) {
152
151
  return {
153
152
  ok: false,
@@ -169,6 +168,7 @@ export function parseWorkItemDetailFromRaw(
169
168
  successMetrics: getSection(sections, "Success metrics"),
170
169
  storiesMarkdown: getSection(sections, "Stories"),
171
170
  children: [],
171
+ promptFeedback: [],
172
172
  commits: parseCommits(getSection(sections, "Commits")),
173
173
  workLog: parseWorkLog(getSection(sections, "Work log")),
174
174
  }
@@ -8,15 +8,14 @@ import type {
8
8
  ProjectEpicList,
9
9
  } from "@/lib/taskmark/epic-types"
10
10
  import {
11
- asNumberOrNull,
12
11
  asString,
13
12
  asStringArray,
14
13
  extractFrontmatter,
15
14
  } from "@/lib/taskmark/frontmatter"
16
15
  import { asContributorList } from "@/lib/taskmark/identity"
17
- import { readTimingFields } from "@/lib/taskmark/timing"
18
16
  import { sortEpicsGeneralFirst } from "@/lib/taskmark/general-epic"
19
- import { progressUnderEpic } from "@/lib/taskmark/count-leaves"
17
+ import { deriveParentRollup } from "@/lib/taskmark/derive-parents"
18
+ import type { BoardIndex } from "@/lib/taskmark/board-index"
20
19
 
21
20
  function listEpicMarkdownFiles(boardPath: string): string[] {
22
21
  const epicsDir = path.join(boardPath, "epics")
@@ -41,7 +40,8 @@ function listEpicMarkdownFiles(boardPath: string): string[] {
41
40
 
42
41
  function parseEpicFile(
43
42
  filePath: string,
44
- project: DiscoveredProject
43
+ project: DiscoveredProject,
44
+ index?: BoardIndex
45
45
  ): { epic?: EpicSummary; error?: EpicParseError } {
46
46
  let raw: string
47
47
  try {
@@ -96,24 +96,26 @@ function parseEpicFile(
96
96
  }
97
97
  }
98
98
 
99
- const progress = progressUnderEpic(project.boardPath, id)
99
+ const derived = deriveParentRollup(project.boardPath, id, "epic", index)
100
100
 
101
101
  return {
102
102
  epic: {
103
103
  id,
104
104
  title,
105
- status: asString(frontmatter.status, "unknown"),
105
+ status: derived.status,
106
106
  priority: asString(frontmatter.priority, "medium"),
107
- size: asString(frontmatter.size, "—"),
108
- points: asNumberOrNull(frontmatter.points),
109
- ...readTimingFields(frontmatter),
107
+ size: derived.size,
108
+ points: derived.points,
109
+ actualMinutes: derived.actualMinutes,
110
+ actualMs: derived.actualMs,
110
111
  tags: asStringArray(frontmatter.tags),
111
112
  reporters: asContributorList(frontmatter.reporters),
112
- resolvers: asContributorList(frontmatter.resolvers),
113
+ resolvers: derived.resolvers,
113
114
  created: asString(frontmatter.created),
114
- completedAt: asString(frontmatter.completed_at),
115
- workItemCount: progress.total,
116
- doneWorkItemCount: progress.done,
115
+ updated: asString(frontmatter.updated),
116
+ completedAt: derived.completedAt,
117
+ workItemCount: derived.leafCount,
118
+ doneWorkItemCount: derived.doneLeafCount,
117
119
  filePath,
118
120
  project: {
119
121
  id: project.id,
@@ -127,14 +129,15 @@ function parseEpicFile(
127
129
 
128
130
  /** Parse all epics under a project's board root (nested taskmark/ or flat *-taskmark). */
129
131
  export function parseEpicsForProject(
130
- project: DiscoveredProject
132
+ project: DiscoveredProject,
133
+ index?: BoardIndex
131
134
  ): ProjectEpicList {
132
135
  const files = listEpicMarkdownFiles(project.boardPath)
133
136
  const epics: EpicSummary[] = []
134
137
  const errors: EpicParseError[] = []
135
138
 
136
139
  for (const filePath of files) {
137
- const result = parseEpicFile(filePath, project)
140
+ const result = parseEpicFile(filePath, project, index)
138
141
  if (result.epic) epics.push(result.epic)
139
142
  if (result.error) errors.push(result.error)
140
143
  }
@@ -149,5 +152,5 @@ export function parseEpicsForProject(
149
152
  export function parseEpicsForProjects(
150
153
  projects: DiscoveredProject[]
151
154
  ): ProjectEpicList[] {
152
- return projects.map(parseEpicsForProject)
155
+ return projects.map((project) => parseEpicsForProject(project))
153
156
  }
@@ -11,6 +11,7 @@ import type {
11
11
  WorkItemsViewRow,
12
12
  } from "@/lib/taskmark/flat-work-item-types"
13
13
  import { compareByStatusThenPriority } from "@/lib/taskmark/list-view-mode"
14
+ import type { BoardIndex } from "@/lib/taskmark/board-index"
14
15
  import { parseEpicsForProject } from "@/lib/taskmark/parse-epics"
15
16
  import { parseItemsForEpic, parseItemsForStory } from "@/lib/taskmark/parse-items"
16
17
  import { parseStoriesForEpic } from "@/lib/taskmark/parse-stories"
@@ -19,9 +20,10 @@ import { parseStoriesForEpic } from "@/lib/taskmark/parse-stories"
19
20
  * Flat table of every epic, story, and task/bug on the active board.
20
21
  */
21
22
  export function parseAllWorkItemsForProject(
22
- project: DiscoveredProject
23
+ project: DiscoveredProject,
24
+ index?: BoardIndex
23
25
  ): FlatWorkItemList {
24
- const epicList = parseEpicsForProject(project)
26
+ const epicList = parseEpicsForProject(project, index)
25
27
  const rows: FlatWorkItemRow[] = []
26
28
  const errors: FlatWorkItemList["errors"] = epicList.errors.map((e) => ({
27
29
  filePath: e.filePath,
@@ -37,7 +39,6 @@ export function parseAllWorkItemsForProject(
37
39
  priority: epic.priority,
38
40
  size: epic.size,
39
41
  points: epic.points,
40
- estimateMinutes: epic.estimateMinutes,
41
42
  actualMinutes: epic.actualMinutes,
42
43
  actualMs: epic.actualMs,
43
44
  epicId: epic.id,
@@ -48,7 +49,7 @@ export function parseAllWorkItemsForProject(
48
49
  project: epic.project,
49
50
  })
50
51
 
51
- const storyList = parseStoriesForEpic(project, epic.id)
52
+ const storyList = parseStoriesForEpic(project, epic.id, index)
52
53
  for (const err of storyList.errors) {
53
54
  errors.push({ filePath: err.filePath, message: err.message })
54
55
  }
@@ -62,7 +63,6 @@ export function parseAllWorkItemsForProject(
62
63
  priority: story.priority,
63
64
  size: story.size,
64
65
  points: story.points,
65
- estimateMinutes: story.estimateMinutes,
66
66
  actualMinutes: story.actualMinutes,
67
67
  actualMs: story.actualMs,
68
68
  epicId: epic.id,
@@ -73,7 +73,7 @@ export function parseAllWorkItemsForProject(
73
73
  project: story.project,
74
74
  })
75
75
 
76
- const items = parseItemsForStory(project, epic.id, story.id)
76
+ const items = parseItemsForStory(project, epic.id, story.id, index)
77
77
  for (const err of items.errors) {
78
78
  errors.push({ filePath: err.filePath, message: err.message })
79
79
  }
@@ -86,7 +86,6 @@ export function parseAllWorkItemsForProject(
86
86
  priority: item.priority,
87
87
  size: item.size,
88
88
  points: item.points,
89
- estimateMinutes: item.estimateMinutes,
90
89
  actualMinutes: item.actualMinutes,
91
90
  actualMs: item.actualMs,
92
91
  epicId: epic.id,
@@ -99,7 +98,7 @@ export function parseAllWorkItemsForProject(
99
98
  }
100
99
  }
101
100
 
102
- const epicItems = parseItemsForEpic(project, epic.id)
101
+ const epicItems = parseItemsForEpic(project, epic.id, index)
103
102
  for (const err of epicItems.errors) {
104
103
  errors.push({ filePath: err.filePath, message: err.message })
105
104
  }
@@ -112,7 +111,6 @@ export function parseAllWorkItemsForProject(
112
111
  priority: item.priority,
113
112
  size: item.size,
114
113
  points: item.points,
115
- estimateMinutes: item.estimateMinutes,
116
114
  actualMinutes: item.actualMinutes,
117
115
  actualMs: item.actualMs,
118
116
  epicId: epic.id,
@@ -130,9 +128,10 @@ export function parseAllWorkItemsForProject(
130
128
 
131
129
  /** All stories across every epic, with epic id/title for UI tags. */
132
130
  export function parseAllStoriesForProject(
133
- project: DiscoveredProject
131
+ project: DiscoveredProject,
132
+ index?: BoardIndex
134
133
  ): ProjectStoriesFlatList {
135
- const epicList = parseEpicsForProject(project)
134
+ const epicList = parseEpicsForProject(project, index)
136
135
  const stories: StoryWithEpicRow[] = []
137
136
  const errors: ProjectStoriesFlatList["errors"] = epicList.errors.map((e) => ({
138
137
  filePath: e.filePath,
@@ -140,7 +139,7 @@ export function parseAllStoriesForProject(
140
139
  }))
141
140
 
142
141
  for (const epic of epicList.epics) {
143
- const storyList = parseStoriesForEpic(project, epic.id)
142
+ const storyList = parseStoriesForEpic(project, epic.id, index)
144
143
  for (const err of storyList.errors) {
145
144
  errors.push({ filePath: err.filePath, message: err.message })
146
145
  }
@@ -152,7 +151,6 @@ export function parseAllStoriesForProject(
152
151
  priority: story.priority,
153
152
  size: story.size,
154
153
  points: story.points,
155
- estimateMinutes: story.estimateMinutes,
156
154
  actualMinutes: story.actualMinutes,
157
155
  actualMs: story.actualMs,
158
156
  epicId: epic.id,
@@ -170,9 +168,10 @@ export function parseAllStoriesForProject(
170
168
 
171
169
  /** All tasks/bugs across the board, with epic and story UI tags. */
172
170
  export function parseAllTasksForProject(
173
- project: DiscoveredProject
171
+ project: DiscoveredProject,
172
+ index?: BoardIndex
174
173
  ): ProjectTasksFlatList {
175
- const epicList = parseEpicsForProject(project)
174
+ const epicList = parseEpicsForProject(project, index)
176
175
  const items: TaskWithParentsRow[] = []
177
176
  const errors: ProjectTasksFlatList["errors"] = epicList.errors.map((e) => ({
178
177
  filePath: e.filePath,
@@ -180,13 +179,13 @@ export function parseAllTasksForProject(
180
179
  }))
181
180
 
182
181
  for (const epic of epicList.epics) {
183
- const storyList = parseStoriesForEpic(project, epic.id)
182
+ const storyList = parseStoriesForEpic(project, epic.id, index)
184
183
  for (const err of storyList.errors) {
185
184
  errors.push({ filePath: err.filePath, message: err.message })
186
185
  }
187
186
 
188
187
  for (const story of storyList.stories) {
189
- const storyItems = parseItemsForStory(project, epic.id, story.id)
188
+ const storyItems = parseItemsForStory(project, epic.id, story.id, index)
190
189
  for (const err of storyItems.errors) {
191
190
  errors.push({ filePath: err.filePath, message: err.message })
192
191
  }
@@ -199,7 +198,6 @@ export function parseAllTasksForProject(
199
198
  priority: item.priority,
200
199
  size: item.size,
201
200
  points: item.points,
202
- estimateMinutes: item.estimateMinutes,
203
201
  actualMinutes: item.actualMinutes,
204
202
  actualMs: item.actualMs,
205
203
  epicId: epic.id,
@@ -212,7 +210,7 @@ export function parseAllTasksForProject(
212
210
  }
213
211
  }
214
212
 
215
- const epicItems = parseItemsForEpic(project, epic.id)
213
+ const epicItems = parseItemsForEpic(project, epic.id, index)
216
214
  for (const err of epicItems.errors) {
217
215
  errors.push({ filePath: err.filePath, message: err.message })
218
216
  }
@@ -225,7 +223,6 @@ export function parseAllTasksForProject(
225
223
  priority: item.priority,
226
224
  size: item.size,
227
225
  points: item.points,
228
- estimateMinutes: item.estimateMinutes,
229
226
  actualMinutes: item.actualMinutes,
230
227
  actualMs: item.actualMs,
231
228
  epicId: epic.id,
@@ -249,13 +246,14 @@ export function parseAllTasksForProject(
249
246
  export function parseWorkItemsForEpic(
250
247
  project: DiscoveredProject,
251
248
  epicId: string,
252
- epicTitle?: string | null
249
+ epicTitle?: string | null,
250
+ index?: BoardIndex
253
251
  ): EpicWorkItemsList {
254
252
  const rows: WorkItemsViewRow[] = []
255
253
  const errors: EpicWorkItemsList["errors"] = []
256
254
  const title = epicTitle ?? null
257
255
 
258
- const storyList = parseStoriesForEpic(project, epicId)
256
+ const storyList = parseStoriesForEpic(project, epicId, index)
259
257
  for (const err of storyList.errors) {
260
258
  errors.push({ filePath: err.filePath, message: err.message })
261
259
  }
@@ -269,7 +267,6 @@ export function parseWorkItemsForEpic(
269
267
  priority: story.priority,
270
268
  size: story.size,
271
269
  points: story.points,
272
- estimateMinutes: story.estimateMinutes,
273
270
  actualMinutes: story.actualMinutes,
274
271
  actualMs: story.actualMs,
275
272
  epicId,
@@ -278,6 +275,7 @@ export function parseWorkItemsForEpic(
278
275
  reporters: story.reporters,
279
276
  resolvers: story.resolvers,
280
277
  created: story.created,
278
+ updated: story.updated,
281
279
  completedAt: story.completedAt,
282
280
  workItemCount: story.workItemCount,
283
281
  doneWorkItemCount: story.doneWorkItemCount,
@@ -286,7 +284,7 @@ export function parseWorkItemsForEpic(
286
284
  })
287
285
  }
288
286
 
289
- const epicItems = parseItemsForEpic(project, epicId)
287
+ const epicItems = parseItemsForEpic(project, epicId, index)
290
288
  for (const err of epicItems.errors) {
291
289
  errors.push({ filePath: err.filePath, message: err.message })
292
290
  }
@@ -299,7 +297,6 @@ export function parseWorkItemsForEpic(
299
297
  priority: item.priority,
300
298
  size: item.size,
301
299
  points: item.points,
302
- estimateMinutes: item.estimateMinutes,
303
300
  actualMinutes: item.actualMinutes,
304
301
  actualMs: item.actualMs,
305
302
  epicId,
@@ -308,6 +305,7 @@ export function parseWorkItemsForEpic(
308
305
  reporters: item.reporters,
309
306
  resolvers: item.resolvers,
310
307
  created: item.created,
308
+ updated: item.updated,
311
309
  completedAt: item.completedAt,
312
310
  workItemCount: 0,
313
311
  doneWorkItemCount: 0,
@@ -331,9 +329,10 @@ export function parseWorkItemsForEpic(
331
329
  * (excludes tasks/bugs that live under a story). Sorted by status then priority.
332
330
  */
333
331
  export function parseWorkItemsViewForProject(
334
- project: DiscoveredProject
332
+ project: DiscoveredProject,
333
+ index?: BoardIndex
335
334
  ): WorkItemsViewList {
336
- const epicList = parseEpicsForProject(project)
335
+ const epicList = parseEpicsForProject(project, index)
337
336
  const rows: WorkItemsViewRow[] = []
338
337
  const errors: WorkItemsViewList["errors"] = epicList.errors.map((e) => ({
339
338
  filePath: e.filePath,
@@ -341,7 +340,12 @@ export function parseWorkItemsViewForProject(
341
340
  }))
342
341
 
343
342
  for (const epic of epicList.epics) {
344
- const epicWorkItems = parseWorkItemsForEpic(project, epic.id, epic.title)
343
+ const epicWorkItems = parseWorkItemsForEpic(
344
+ project,
345
+ epic.id,
346
+ epic.title,
347
+ index
348
+ )
345
349
  for (const err of epicWorkItems.errors) {
346
350
  errors.push({ filePath: err.filePath, message: err.message })
347
351
  }