fleetlens 0.4.0 → 0.6.0

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 (440) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +16 -7
  3. package/app/apps/web/.next/build-manifest.json +7 -7
  4. package/app/apps/web/.next/prerender-manifest.json +3 -3
  5. package/app/apps/web/.next/required-server-files.json +2 -1
  6. package/app/apps/web/.next/routes-manifest.json +86 -24
  7. package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +4 -4
  8. package/app/apps/web/.next/server/app/_global-error/page.js +1 -1
  9. package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.rsc +7 -7
  13. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/app/apps/web/.next/server/app/_not-found/page/build-manifest.json +4 -4
  19. package/app/apps/web/.next/server/app/_not-found/page.js +5 -4
  20. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/app/apps/web/.next/server/app/api/digest/day/[date]/route/app-paths-manifest.json +3 -0
  23. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +9 -0
  24. package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/day/[date]}/route.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/api/digest/day/[date]/route_client-reference-manifest.js +3 -0
  26. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route/app-paths-manifest.json +3 -0
  27. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +9 -0
  28. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -0
  29. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route_client-reference-manifest.js +3 -0
  30. package/app/apps/web/.next/server/app/api/digest/month-index/route/app-paths-manifest.json +3 -0
  31. package/app/apps/web/.next/server/app/api/digest/month-index/route.js +7 -0
  32. package/app/apps/web/.next/server/app/api/{insights/months-index → digest/month-index}/route.js.nft.json +1 -1
  33. package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route_client-reference-manifest.js +1 -1
  34. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route/app-paths-manifest.json +3 -0
  35. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +9 -0
  36. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -0
  37. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route_client-reference-manifest.js +3 -0
  38. package/app/apps/web/.next/server/app/api/digest/week-index/route/app-paths-manifest.json +3 -0
  39. package/app/apps/web/.next/server/app/api/digest/week-index/route.js +7 -0
  40. package/app/apps/web/.next/server/app/api/{insights/weeks-index → digest/week-index}/route.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/api/digest/week-index/route_client-reference-manifest.js +3 -0
  42. package/app/apps/web/.next/server/app/api/jobs/route/app-paths-manifest.json +3 -0
  43. package/app/apps/web/.next/server/app/api/jobs/route.js +6 -0
  44. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -0
  45. package/app/apps/web/.next/server/app/api/jobs/route_client-reference-manifest.js +3 -0
  46. package/app/apps/web/.next/server/app/api/runs/[runId]/route/app-paths-manifest.json +3 -0
  47. package/app/apps/web/.next/server/app/api/runs/[runId]/route/build-manifest.json +9 -0
  48. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +6 -0
  49. package/app/apps/web/.next/server/app/api/{insights/saved → runs/[runId]}/route.js.nft.json +1 -1
  50. package/app/apps/web/.next/server/app/api/runs/[runId]/route_client-reference-manifest.js +3 -0
  51. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/app-paths-manifest.json +3 -0
  52. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/build-manifest.json +9 -0
  53. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/server-reference-manifest.json +4 -0
  54. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js +6 -0
  55. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.map +5 -0
  56. package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → runs/[runId]/stream}/route.js.nft.json +1 -1
  57. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route_client-reference-manifest.js +3 -0
  58. package/app/apps/web/.next/server/app/api/runs/route/app-paths-manifest.json +3 -0
  59. package/app/apps/web/.next/server/app/api/runs/route/build-manifest.json +9 -0
  60. package/app/apps/web/.next/server/app/api/runs/route/server-reference-manifest.json +4 -0
  61. package/app/apps/web/.next/server/app/api/runs/route.js +6 -0
  62. package/app/apps/web/.next/server/app/api/runs/route.js.map +5 -0
  63. package/app/apps/web/.next/server/app/api/{insights → runs}/route.js.nft.json +1 -1
  64. package/app/apps/web/.next/server/app/api/runs/route_client-reference-manifest.js +3 -0
  65. package/app/apps/web/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
  66. package/app/apps/web/.next/server/app/api/settings/route/build-manifest.json +9 -0
  67. package/app/apps/web/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
  68. package/app/apps/web/.next/server/app/api/settings/route.js +10 -0
  69. package/app/apps/web/.next/server/app/api/settings/route.js.map +5 -0
  70. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -0
  71. package/app/apps/web/.next/server/app/api/{insights → settings}/route_client-reference-manifest.js +1 -1
  72. package/app/apps/web/.next/server/app/day/[date]/page/app-paths-manifest.json +3 -0
  73. package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/build-manifest.json +4 -4
  74. package/app/apps/web/.next/server/app/day/[date]/page/server-reference-manifest.json +4 -0
  75. package/app/apps/web/.next/server/app/day/[date]/page.js +18 -0
  76. package/app/apps/web/.next/server/app/day/[date]/page.js.map +5 -0
  77. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -0
  78. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +3 -0
  79. package/app/apps/web/.next/server/app/day/page/app-paths-manifest.json +3 -0
  80. package/app/apps/web/.next/server/app/day/page/build-manifest.json +17 -0
  81. package/app/apps/web/.next/server/app/day/page/next-font-manifest.json +6 -0
  82. package/app/apps/web/.next/server/app/day/page/react-loadable-manifest.json +1 -0
  83. package/app/apps/web/.next/server/app/day/page/server-reference-manifest.json +4 -0
  84. package/app/apps/web/.next/server/app/{insights/print/[key] → day}/page.js +11 -10
  85. package/app/apps/web/.next/server/app/day/page.js.map +5 -0
  86. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -0
  87. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +3 -0
  88. package/app/apps/web/.next/server/app/digest/[date]/page/app-paths-manifest.json +3 -0
  89. package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +17 -0
  90. package/app/apps/web/.next/server/app/digest/[date]/page/next-font-manifest.json +6 -0
  91. package/app/apps/web/.next/server/app/digest/[date]/page/react-loadable-manifest.json +1 -0
  92. package/app/apps/web/.next/server/app/digest/[date]/page/server-reference-manifest.json +4 -0
  93. package/app/apps/web/.next/server/app/digest/[date]/page.js +17 -0
  94. package/app/apps/web/.next/server/app/digest/[date]/page.js.map +5 -0
  95. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -0
  96. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +3 -0
  97. package/app/apps/web/.next/server/app/digest/page/app-paths-manifest.json +3 -0
  98. package/app/apps/web/.next/server/app/digest/page/build-manifest.json +17 -0
  99. package/app/apps/web/.next/server/app/digest/page/next-font-manifest.json +6 -0
  100. package/app/apps/web/.next/server/app/digest/page/react-loadable-manifest.json +1 -0
  101. package/app/apps/web/.next/server/app/digest/page/server-reference-manifest.json +4 -0
  102. package/app/apps/web/.next/server/app/digest/page.js +17 -0
  103. package/app/apps/web/.next/server/app/digest/page.js.map +5 -0
  104. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -0
  105. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +3 -0
  106. package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +4 -4
  107. package/app/apps/web/.next/server/app/insights/[key]/page.js +7 -5
  108. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  109. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  110. package/app/apps/web/.next/server/app/insights/page/build-manifest.json +4 -4
  111. package/app/apps/web/.next/server/app/insights/page.js +7 -5
  112. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  113. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  114. package/app/apps/web/.next/server/app/page/build-manifest.json +4 -4
  115. package/app/apps/web/.next/server/app/page.js +7 -6
  116. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  117. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  118. package/app/apps/web/.next/server/app/parallelism/page/build-manifest.json +4 -4
  119. package/app/apps/web/.next/server/app/parallelism/page.js +6 -5
  120. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  121. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  122. package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +4 -4
  123. package/app/apps/web/.next/server/app/projects/[slug]/page.js +6 -5
  124. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  125. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  126. package/app/apps/web/.next/server/app/projects/page/build-manifest.json +4 -4
  127. package/app/apps/web/.next/server/app/projects/page.js +5 -4
  128. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  129. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  130. package/app/apps/web/.next/server/app/runs/page/app-paths-manifest.json +3 -0
  131. package/app/apps/web/.next/server/app/runs/page/build-manifest.json +17 -0
  132. package/app/apps/web/.next/server/app/runs/page/next-font-manifest.json +6 -0
  133. package/app/apps/web/.next/server/app/runs/page/react-loadable-manifest.json +1 -0
  134. package/app/apps/web/.next/server/app/runs/page/server-reference-manifest.json +4 -0
  135. package/app/apps/web/.next/server/app/runs/page.js +17 -0
  136. package/app/apps/web/.next/server/app/runs/page.js.map +5 -0
  137. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -0
  138. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +3 -0
  139. package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +4 -4
  140. package/app/apps/web/.next/server/app/sessions/[id]/page.js +5 -4
  141. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  142. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  143. package/app/apps/web/.next/server/app/sessions/page/build-manifest.json +4 -4
  144. package/app/apps/web/.next/server/app/sessions/page.js +5 -4
  145. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  146. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  147. package/app/apps/web/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  148. package/app/apps/web/.next/server/app/settings/page/build-manifest.json +17 -0
  149. package/app/apps/web/.next/server/app/settings/page/next-font-manifest.json +6 -0
  150. package/app/apps/web/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  151. package/app/apps/web/.next/server/app/settings/page/server-reference-manifest.json +4 -0
  152. package/app/apps/web/.next/server/app/settings/page.js +18 -0
  153. package/app/apps/web/.next/server/app/settings/page.js.map +5 -0
  154. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -0
  155. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  156. package/app/apps/web/.next/server/app/usage/page/build-manifest.json +4 -4
  157. package/app/apps/web/.next/server/app/usage/page.js +6 -5
  158. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  159. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  160. package/app/apps/web/.next/server/app-paths-manifest.json +16 -7
  161. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_digest_week_[startDate]_route_actions_0klqqsh.js +3 -0
  162. package/app/apps/web/.next/server/chunks/09og__next-internal_server_app_api_digest_month_[yearMonth]_route_actions_0i4ielu.js +3 -0
  163. package/app/apps/web/.next/server/chunks/[externals]__0o43ejh._.js +3 -0
  164. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0-vgrh1._.js +3 -0
  165. package/app/apps/web/.next/server/chunks/[root-of-the-server]__00n3f9y._.js +3 -0
  166. package/app/apps/web/.next/server/chunks/[root-of-the-server]__02zukjw._.js +3 -0
  167. package/app/apps/web/.next/server/chunks/[root-of-the-server]__067~im1._.js +6 -0
  168. package/app/apps/web/.next/server/chunks/[root-of-the-server]__06b4cj-._.js +3 -0
  169. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +9 -0
  170. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e8n_x4._.js +3 -0
  171. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +9 -0
  172. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +9 -0
  173. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_day_[date]_route_actions_09sxie5.js +3 -0
  174. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_month-index_route_actions_0wldpbu.js +3 -0
  175. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_week-index_route_actions_12c2wj2.js +3 -0
  176. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_jobs_route_actions_08kx~8-.js +3 -0
  177. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_route_actions_0dfcghc.js +3 -0
  178. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_stream_route_actions_0.8e8-k.js +3 -0
  179. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_route_actions_0xyx82f.js +3 -0
  180. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_settings_route_actions_0.xv7sx.js +3 -0
  181. package/app/apps/web/.next/server/chunks/node_modules_next_036my~r._.js +49 -0
  182. package/app/apps/web/.next/server/chunks/packages_0e7q9u_._.js +3 -0
  183. package/app/apps/web/.next/server/chunks/packages_0n6p2ot._.js +3 -0
  184. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +379 -0
  185. package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_0bc7ptm.js +1 -1
  186. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-1_njm._.js +3 -0
  187. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-94ji~._.js +3 -0
  188. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__13xpdx0._.js → [root-of-the-server]__03uoeiw._.js} +2 -2
  189. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0_6.inc._.js +1 -1
  190. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +8 -0
  191. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gio_ck._.js +1 -1
  192. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08.d5ia._.js → [root-of-the-server]__0jdyefm._.js} +10 -10
  193. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ln9jsw._.js +3 -0
  194. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0z45d0g._.js → [root-of-the-server]__0lz4a~g._.js} +2 -48
  195. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o1_g.~._.js +3 -0
  196. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +3 -0
  197. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +3 -0
  198. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0euu8sa._.js → [root-of-the-server]__0u39afl._.js} +2 -2
  199. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0u5d7de._.js +12 -0
  200. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +3 -3
  201. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wwa6gh._.js +3 -0
  202. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xy1qim._.js +3 -0
  203. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~_8vff._.js +3 -0
  204. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10srpu0._.js +3 -0
  205. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11v.eqw._.js +1 -1
  206. package/app/apps/web/.next/server/chunks/ssr/_02s1n-x._.js +8 -0
  207. package/app/apps/web/.next/server/chunks/ssr/_0fjbf--._.js +3 -0
  208. package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +3 -0
  209. package/app/apps/web/.next/server/chunks/ssr/_0wj750k._.js +3 -0
  210. package/app/apps/web/.next/server/chunks/ssr/_0woap-3._.js +1 -1
  211. package/app/apps/web/.next/server/chunks/ssr/{_0xies90._.js → _0xu2pvc._.js} +2 -2
  212. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_[date]_page_actions_0u2kxb..js +3 -0
  213. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_page_actions_1042maj.js +3 -0
  214. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_[date]_page_actions_0olu967.js +3 -0
  215. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_page_actions_0bl.eil.js +3 -0
  216. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_runs_page_actions_0485qy7.js +3 -0
  217. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_settings_page_actions_0f6epye.js +3 -0
  218. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +3 -0
  219. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_settings_ai-features-form_tsx_01p699p._.js +3 -0
  220. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +1 -1
  221. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +6 -0
  222. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +16 -0
  223. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0xs658s._.js +10 -0
  224. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_runs-live-board_tsx_0r6dkdq._.js +3 -0
  225. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_usage-charts-dashboard_tsx_0bgr_uv._.js +1 -1
  226. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_usage-data_ts_0xtv99n._.js +3 -0
  227. package/app/apps/web/.next/server/chunks/ssr/node_modules_0i2xw~e._.js +3 -0
  228. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +1 -1
  229. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0d3d4wn.js +4 -0
  230. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0edz1ko.js +4 -0
  231. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0eq.n-n.js +4 -0
  232. package/app/apps/web/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0vz7_px.js → node_modules_next_dist_esm_build_templates_app-page_0hcvt-s.js} +3 -3
  233. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nd5zu0.js +4 -0
  234. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11j1qy0.js +4 -0
  235. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12n1lw_.js +1 -1
  236. package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +3 -0
  237. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
  238. package/app/apps/web/.next/server/functions-config-manifest.json +11 -6
  239. package/app/apps/web/.next/server/middleware-build-manifest.js +7 -7
  240. package/app/apps/web/.next/server/pages/500.html +1 -1
  241. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  242. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  243. package/app/apps/web/.next/static/chunks/0-yc2_pjxwwuq.js +1 -0
  244. package/app/apps/web/.next/static/chunks/0257pdz1-imal.js +2 -0
  245. package/app/apps/web/.next/static/chunks/05m.oz3kmf1p7.js +1 -0
  246. package/app/apps/web/.next/static/chunks/{0pqt~8bl3ukh4.js → 073081qv4uyn8.js} +1 -1
  247. package/app/apps/web/.next/static/chunks/{0018dy-m-kusj.js → 07lbm-sdh9c2j.js} +1 -1
  248. package/app/apps/web/.next/static/chunks/0858bgw2i4vob.js +1 -0
  249. package/app/apps/web/.next/static/chunks/0_7303jr0sf0w.js +10 -0
  250. package/app/apps/web/.next/static/chunks/0byz8fqw.exef.js +1 -0
  251. package/app/apps/web/.next/static/chunks/0coa1800xqgfj.js +1 -0
  252. package/app/apps/web/.next/static/chunks/0fs3gxea5h0s3.css +1 -0
  253. package/app/apps/web/.next/static/chunks/0k1psab.bybh9.js +14 -0
  254. package/app/apps/web/.next/static/chunks/0k9pksi_i.odf.js +1 -0
  255. package/app/apps/web/.next/static/chunks/0m62vx92~0_0d.js +1 -0
  256. package/app/apps/web/.next/static/chunks/0mc8aa8z.0-5l.js +8 -0
  257. package/app/apps/web/.next/static/chunks/0mykrrv810ra-.js +31 -0
  258. package/app/apps/web/.next/static/chunks/0o9ayt8sknubd.js +1 -0
  259. package/app/apps/web/.next/static/chunks/0osdgl2.9cl1q.js +6 -0
  260. package/app/apps/web/.next/static/chunks/0xfu09fn_358k.js +4 -0
  261. package/app/apps/web/.next/static/chunks/171za22fv684..js +6 -0
  262. package/app/apps/web/.next/static/chunks/17u2ww8ya5dv1.js +6 -0
  263. package/app/apps/web/.next/static/chunks/{turbopack-169w-1._23ra_.js → turbopack-0_p36yduv.waj.js} +1 -1
  264. package/app/apps/web/app/api/digest/day/[date]/route.ts +152 -0
  265. package/app/apps/web/app/api/digest/month/[yearMonth]/route.ts +147 -0
  266. package/app/apps/web/app/api/digest/month-index/route.ts +103 -0
  267. package/app/apps/web/app/api/digest/week/[startDate]/route.ts +149 -0
  268. package/app/apps/web/app/api/{insights/weeks-index → digest/week-index}/route.ts +45 -33
  269. package/app/apps/web/app/api/jobs/route.ts +8 -0
  270. package/app/apps/web/app/api/runs/[runId]/route.ts +64 -0
  271. package/app/apps/web/app/api/runs/[runId]/stream/route.ts +154 -0
  272. package/app/apps/web/app/api/runs/route.ts +266 -0
  273. package/app/apps/web/app/api/settings/route.ts +35 -0
  274. package/app/apps/web/app/day/[date]/day-view.tsx +193 -0
  275. package/app/apps/web/app/day/[date]/page.tsx +175 -0
  276. package/app/apps/web/app/day/page.tsx +8 -0
  277. package/app/apps/web/app/digest/[date]/page.tsx +15 -0
  278. package/app/apps/web/app/digest/page.tsx +7 -0
  279. package/app/apps/web/app/insights/[key]/page.tsx +106 -48
  280. package/app/apps/web/app/insights/page.tsx +133 -3
  281. package/app/apps/web/app/layout.tsx +23 -3
  282. package/app/apps/web/app/page.tsx +33 -4
  283. package/app/apps/web/app/parallelism/gantt-chart.tsx +67 -1
  284. package/app/apps/web/app/parallelism/page.tsx +8 -278
  285. package/app/apps/web/app/projects/[slug]/page.tsx +153 -0
  286. package/app/apps/web/app/projects/page.tsx +49 -4
  287. package/app/apps/web/app/projects/projects-view.tsx +79 -68
  288. package/app/apps/web/app/runs/page.tsx +21 -0
  289. package/app/apps/web/app/sessions/[id]/page.tsx +12 -1
  290. package/app/apps/web/app/sessions/[id]/session-view.tsx +569 -21
  291. package/app/apps/web/app/sessions/page.tsx +19 -3
  292. package/app/apps/web/app/sessions/sessions-grid.tsx +172 -131
  293. package/app/apps/web/app/settings/ai-features-form.tsx +45 -0
  294. package/app/apps/web/app/settings/page.tsx +20 -0
  295. package/app/apps/web/app/usage/page.tsx +45 -3
  296. package/app/apps/web/components/auto-generate-yesterday.tsx +96 -0
  297. package/app/apps/web/components/backfill-drawer.tsx +309 -0
  298. package/app/apps/web/components/dashboard-view.tsx +4 -2
  299. package/app/apps/web/components/date-nav.tsx +385 -0
  300. package/app/apps/web/components/day-digest-view.tsx +180 -0
  301. package/app/apps/web/components/day-digest.tsx +489 -0
  302. package/app/apps/web/components/flag-chip.tsx +54 -0
  303. package/app/apps/web/components/goal-bar.tsx +63 -0
  304. package/app/apps/web/components/heatmap.tsx +78 -1
  305. package/app/apps/web/components/helpfulness-sparkline.tsx +82 -0
  306. package/app/apps/web/components/insights-history.tsx +211 -0
  307. package/app/apps/web/components/insights-top-bar.tsx +216 -0
  308. package/app/apps/web/components/job-queue-widget.tsx +274 -0
  309. package/app/apps/web/components/live-sessions-widget.tsx +38 -3
  310. package/app/apps/web/components/month-digest-view.tsx +138 -0
  311. package/app/apps/web/components/month-digest.tsx +216 -0
  312. package/app/apps/web/components/outcome-mix-row.tsx +37 -0
  313. package/app/apps/web/components/outcome-pill.tsx +101 -0
  314. package/app/apps/web/components/previous-cycles-trend.tsx +155 -0
  315. package/app/apps/web/components/recent-days-panel.tsx +83 -0
  316. package/app/apps/web/components/runs-live-board.tsx +513 -0
  317. package/app/apps/web/components/sidebar.tsx +38 -4
  318. package/app/apps/web/components/usage-chart-range.tsx +58 -6
  319. package/app/apps/web/components/usage-chart.tsx +94 -7
  320. package/app/apps/web/components/usage-charts-dashboard.tsx +20 -1
  321. package/app/apps/web/components/week-digest-view.tsx +226 -0
  322. package/app/apps/web/components/week-digest.tsx +2128 -0
  323. package/app/apps/web/components/yesterday-hero.tsx +110 -0
  324. package/app/apps/web/lib/auto-week-fire.ts +37 -0
  325. package/app/apps/web/lib/calibration-data.ts +171 -0
  326. package/app/apps/web/lib/entries-index.ts +174 -0
  327. package/app/apps/web/lib/entries.ts +72 -0
  328. package/app/apps/web/lib/inflight-coalesce.test.ts +43 -0
  329. package/app/apps/web/lib/inflight-coalesce.ts +19 -0
  330. package/app/apps/web/lib/jobs.ts +170 -0
  331. package/app/apps/web/lib/usage-data.ts +37 -0
  332. package/app/apps/web/lib/validate-settings.test.ts +25 -0
  333. package/app/apps/web/lib/validate-settings.ts +9 -0
  334. package/app/apps/web/next.config.ts +1 -1
  335. package/app/apps/web/package.json +4 -2
  336. package/app/apps/web/server.js +1 -1
  337. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  338. package/app/apps/web/vitest.config.ts +9 -0
  339. package/dist/daemon-worker.js +1758 -713
  340. package/dist/index.js +11308 -1888
  341. package/package.json +4 -1
  342. package/app/apps/web/.next/server/app/api/insights/months-index/route/app-paths-manifest.json +0 -3
  343. package/app/apps/web/.next/server/app/api/insights/months-index/route.js +0 -7
  344. package/app/apps/web/.next/server/app/api/insights/months-index/route_client-reference-manifest.js +0 -3
  345. package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route/app-paths-manifest.json +0 -3
  346. package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route.js +0 -6
  347. package/app/apps/web/.next/server/app/api/insights/route/app-paths-manifest.json +0 -3
  348. package/app/apps/web/.next/server/app/api/insights/route.js +0 -8
  349. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route/app-paths-manifest.json +0 -3
  350. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route.js +0 -6
  351. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route_client-reference-manifest.js +0 -3
  352. package/app/apps/web/.next/server/app/api/insights/saved/route/app-paths-manifest.json +0 -3
  353. package/app/apps/web/.next/server/app/api/insights/saved/route.js +0 -6
  354. package/app/apps/web/.next/server/app/api/insights/saved/route_client-reference-manifest.js +0 -3
  355. package/app/apps/web/.next/server/app/api/insights/weeks-index/route/app-paths-manifest.json +0 -3
  356. package/app/apps/web/.next/server/app/api/insights/weeks-index/route.js +0 -7
  357. package/app/apps/web/.next/server/app/api/insights/weeks-index/route_client-reference-manifest.js +0 -3
  358. package/app/apps/web/.next/server/app/insights/print/[key]/page/app-paths-manifest.json +0 -3
  359. package/app/apps/web/.next/server/app/insights/print/[key]/page.js.nft.json +0 -1
  360. package/app/apps/web/.next/server/app/insights/print/[key]/page_client-reference-manifest.js +0 -3
  361. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_months-index_route_actions_0~h~zci.js +0 -3
  362. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_saved_[key]_route_actions_0a5j9yw.js +0 -3
  363. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_weeks-index_route_actions_0hh-1c7.js +0 -3
  364. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.hmj0z._.js +0 -3
  365. package/app/apps/web/.next/server/chunks/[root-of-the-server]__01h_g-p._.js +0 -3
  366. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nh-z10._.js +0 -3
  367. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ri7q~r._.js +0 -3
  368. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0rr1~~x._.js +0 -3
  369. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0s0gv.0._.js +0 -3
  370. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_pdf_[key]_route_actions_0lu-lnx.js +0 -3
  371. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_route_actions_0h8l5lz.js +0 -3
  372. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_saved_route_actions_13rlblw.js +0 -3
  373. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_00t2xj6.js +0 -68
  374. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0.tsxpj._.js +0 -3
  375. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00z7zlm._.js +0 -3
  376. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08pen0k._.js +0 -3
  377. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0b323~k._.js +0 -8
  378. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gx-4qa._.js +0 -3
  379. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wv27wt._.js +0 -3
  380. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__13itnvx._.js +0 -3
  381. package/app/apps/web/.next/server/chunks/ssr/_09n75_5._.js +0 -8
  382. package/app/apps/web/.next/server/chunks/ssr/_0r~__0v._.js +0 -12
  383. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_insights_print_[key]_page_actions_0a853fw.js +0 -3
  384. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_parallelism_08vub.0._.js +0 -3
  385. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +0 -8
  386. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0bbo_pd._.js +0 -8
  387. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insight-report_tsx_13q2a-c._.js +0 -12
  388. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insights-view_tsx_11730ta._.js +0 -6
  389. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0nqz8dw._.js +0 -3
  390. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +0 -3
  391. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_analytics_0k4dgst.js +0 -3
  392. package/app/apps/web/.next/static/chunks/028_pmk40b69_.js +0 -6
  393. package/app/apps/web/.next/static/chunks/03.mv4y4.w-vb.js +0 -6
  394. package/app/apps/web/.next/static/chunks/03_7xtpi9sv4g.js +0 -4
  395. package/app/apps/web/.next/static/chunks/03g5dw5eskotd.js +0 -6
  396. package/app/apps/web/.next/static/chunks/063oimt30jeo9.js +0 -10
  397. package/app/apps/web/.next/static/chunks/08c1pcrocqq5s.js +0 -6
  398. package/app/apps/web/.next/static/chunks/0e-wrhqh4h3r5.js +0 -2
  399. package/app/apps/web/.next/static/chunks/0fc6dk2qtokwh.js +0 -1
  400. package/app/apps/web/.next/static/chunks/0i7er7_bfab36.js +0 -10
  401. package/app/apps/web/.next/static/chunks/0ipytyi01h0ta.js +0 -1
  402. package/app/apps/web/.next/static/chunks/0lsznd4_avzhv.js +0 -6
  403. package/app/apps/web/.next/static/chunks/0lty3v_i9mde7.js +0 -1
  404. package/app/apps/web/.next/static/chunks/0vekjjj4pidlz.css +0 -1
  405. package/app/apps/web/.next/static/chunks/137uw2-qbro07.js +0 -31
  406. package/app/apps/web/app/api/insights/months-index/route.ts +0 -80
  407. package/app/apps/web/app/api/insights/pdf/[key]/route.ts +0 -45
  408. package/app/apps/web/app/api/insights/route.ts +0 -508
  409. package/app/apps/web/app/api/insights/saved/[key]/route.ts +0 -11
  410. package/app/apps/web/app/api/insights/saved/route.ts +0 -9
  411. package/app/apps/web/app/insights/print/[key]/page.tsx +0 -73
  412. package/app/apps/web/components/insight-report.tsx +0 -1031
  413. package/app/apps/web/components/insights-view.tsx +0 -647
  414. package/app/apps/web/lib/ai/insights-prompt.ts +0 -71
  415. package/app/apps/web/lib/ai/saved-reports.ts +0 -83
  416. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/build-manifest.json +0 -0
  417. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/server-reference-manifest.json +0 -0
  418. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route.js.map +0 -0
  419. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/build-manifest.json +0 -0
  420. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/server-reference-manifest.json +0 -0
  421. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route.js.map +0 -0
  422. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/build-manifest.json +0 -0
  423. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/server-reference-manifest.json +0 -0
  424. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route.js.map +0 -0
  425. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/build-manifest.json +0 -0
  426. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/server-reference-manifest.json +0 -0
  427. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route.js.map +0 -0
  428. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/build-manifest.json +0 -0
  429. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/server-reference-manifest.json +0 -0
  430. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route.js.map +0 -0
  431. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/build-manifest.json +0 -0
  432. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/server-reference-manifest.json +0 -0
  433. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route.js.map +0 -0
  434. /package/app/apps/web/.next/server/app/{insights/print/[key]/page → api/runs/[runId]/route}/server-reference-manifest.json +0 -0
  435. /package/app/apps/web/.next/server/app/{insights/print/[key]/page.js.map → api/runs/[runId]/route.js.map} +0 -0
  436. /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/next-font-manifest.json +0 -0
  437. /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/react-loadable-manifest.json +0 -0
  438. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_buildManifest.js +0 -0
  439. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_clientMiddlewareManifest.js +0 -0
  440. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_ssgManifest.js +0 -0
@@ -0,0 +1,110 @@
1
+ import Link from "next/link";
2
+ import { readDayDigest, listEntriesForDay } from "@claude-lens/entries/fs";
3
+ import { buildDeterministicDigest, readSettings } from "@claude-lens/entries/node";
4
+ import type { DayDigest } from "@claude-lens/entries";
5
+ import { yesterdayLocal, toLocalDay } from "@/lib/entries";
6
+ import { AutoGenerateYesterday } from "./auto-generate-yesterday";
7
+
8
+ function fmtDateShort(date: string): string {
9
+ return new Date(`${date}T12:00:00`).toLocaleDateString("en-US", {
10
+ weekday: "long", month: "short", day: "numeric",
11
+ });
12
+ }
13
+
14
+ function firstSentence(s: string | null): string | null {
15
+ if (!s) return null;
16
+ const m = /^[^.!?]+[.!?]/.exec(s);
17
+ return m ? m[0] : s;
18
+ }
19
+
20
+ function truncate(s: string, n: number): string {
21
+ return s.length > n ? s.slice(0, n - 1) + "…" : s;
22
+ }
23
+
24
+ /** Returns the most recent local day (< today) that has any entries. */
25
+ function mostRecentActiveDay(): string | null {
26
+ for (let i = 1; i <= 30; i++) {
27
+ const d = toLocalDay(Date.now() - i * 86_400_000);
28
+ if (listEntriesForDay(d).length > 0) return d;
29
+ }
30
+ return null;
31
+ }
32
+
33
+ export function YesterdayHero() {
34
+ const aiEnabled = readSettings().ai_features.enabled;
35
+ const yesterday = yesterdayLocal();
36
+ let date = yesterday;
37
+ let entries = listEntriesForDay(yesterday);
38
+ let fallback = false;
39
+
40
+ if (entries.length === 0) {
41
+ const recent = mostRecentActiveDay();
42
+ if (recent) {
43
+ date = recent;
44
+ entries = listEntriesForDay(recent);
45
+ fallback = true;
46
+ }
47
+ }
48
+
49
+ if (entries.length === 0) {
50
+ return (
51
+ <div className="af-panel" style={{ padding: 24, textAlign: "center" }}>
52
+ <p style={{ color: "var(--af-text-secondary)" }}>
53
+ No recent activity yet. Once you run some Claude Code sessions, your daily digest will appear here.
54
+ </p>
55
+ </div>
56
+ );
57
+ }
58
+
59
+ const persisted = readDayDigest(date);
60
+ const digest: DayDigest = persisted ?? buildDeterministicDigest(date, entries);
61
+ // "Missing" = no persisted digest on disk and the deterministic fallback
62
+ // has no narrative. The auto-gen trigger looks at this to decide.
63
+ const narrativeMissing = aiEnabled && !fallback && digest.headline === null;
64
+
65
+ const headline = digest.headline
66
+ ?? `Worked ${Math.round(digest.agent_min)}m across ${digest.projects.length} project${digest.projects.length === 1 ? "" : "s"}${digest.shipped.length > 0 ? `; shipped ${digest.shipped.length} PR${digest.shipped.length === 1 ? "" : "s"}` : ""}.`;
67
+
68
+ const wentWell = firstSentence(digest.what_went_well);
69
+ const friction = firstSentence(digest.what_hit_friction);
70
+
71
+ return (
72
+ <div className="af-panel" style={{ padding: 20, display: "flex", flexDirection: "column", gap: 12 }}>
73
+ <div>
74
+ <div style={{
75
+ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap",
76
+ fontSize: 11, color: "var(--af-text-tertiary)",
77
+ textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600,
78
+ }}>
79
+ <span>{fallback ? "Last active" : "Yesterday"} · {fmtDateShort(date)}</span>
80
+ <AutoGenerateYesterday yesterdayDate={date} missing={narrativeMissing} />
81
+ </div>
82
+ <h2 style={{ fontSize: 17, fontWeight: 600, margin: "8px 0 0", lineHeight: 1.35 }}>
83
+ {truncate(headline, 180)}
84
+ </h2>
85
+ </div>
86
+ <div style={{ fontSize: 12, color: "var(--af-text-secondary)", fontFamily: "var(--font-mono)" }}>
87
+ {Math.round(digest.agent_min)}m agent time · {digest.projects.length} project{digest.projects.length === 1 ? "" : "s"} · {digest.shipped.length} PR{digest.shipped.length === 1 ? "" : "s"} shipped
88
+ </div>
89
+ {(wentWell || friction) && (
90
+ <div style={{ fontSize: 13, display: "flex", flexDirection: "column", gap: 4 }}>
91
+ {wentWell && <div><span style={{ color: "#48bb78" }}>✓</span> {truncate(wentWell, 160)}</div>}
92
+ {friction && <div><span style={{ color: "#ed8936" }}>⚠</span> {truncate(friction, 160)}</div>}
93
+ </div>
94
+ )}
95
+ {!aiEnabled && (
96
+ <div style={{ fontSize: 11, color: "var(--af-text-tertiary)" }}>
97
+ <Link href="/settings" style={{ color: "var(--af-accent)" }}>Enable AI features</Link> to see daily narratives.
98
+ </div>
99
+ )}
100
+ <div style={{ display: "flex", gap: 12, marginTop: 4 }}>
101
+ <Link href={`/digest/${date}`} style={{ fontSize: 12, color: "var(--af-accent)" }}>
102
+ Open full digest →
103
+ </Link>
104
+ <Link href="/insights" style={{ fontSize: 12, color: "var(--af-accent)" }}>
105
+ Weekly insight report →
106
+ </Link>
107
+ </div>
108
+ </div>
109
+ );
110
+ }
@@ -0,0 +1,37 @@
1
+ import "server-only";
2
+ import { existsSync, readFileSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
3
+ import { join, dirname } from "node:path";
4
+ import { homedir } from "node:os";
5
+
6
+ function autoFireFile(): string {
7
+ return process.env.CCLENS_AUTO_WEEK_FILE
8
+ ?? join(homedir(), ".cclens", "auto-week-fired-at");
9
+ }
10
+
11
+ const MONDAY_RE = /^\d{4}-\d{2}-\d{2}$/;
12
+
13
+ /**
14
+ * Returns true if this call is the one that should trigger auto-fire for `monday`.
15
+ * Atomically updates the on-disk record so subsequent calls in the same ISO week
16
+ * return false. Idempotent across server restarts.
17
+ *
18
+ * Corrupt/unreadable file is treated as "absent" — the caller will fire and
19
+ * the file will be rewritten with a clean Monday line.
20
+ */
21
+ export function shouldAutoFireWeek(monday: string): boolean {
22
+ const file = autoFireFile();
23
+ let prev: string | null = null;
24
+ if (existsSync(file)) {
25
+ try {
26
+ const raw = readFileSync(file, "utf8").trim();
27
+ if (MONDAY_RE.test(raw)) prev = raw;
28
+ } catch { /* corrupt — treat as absent */ }
29
+ }
30
+ if (prev === monday) return false;
31
+
32
+ mkdirSync(dirname(file), { recursive: true });
33
+ const tmp = `${file}.tmp`;
34
+ writeFileSync(tmp, monday + "\n", "utf8");
35
+ renameSync(tmp, file);
36
+ return true;
37
+ }
@@ -0,0 +1,171 @@
1
+ import "server-only";
2
+ import { cache } from "react";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { homedir } from "node:os";
6
+ import { loadCalibrationCurve } from "@claude-lens/parser/fs";
7
+ import type { PlanTier, RateSource } from "@claude-lens/parser";
8
+
9
+ // One point on the calibration overlay — pairs the daemon's measured
10
+ // utilization (when a snapshot landed in the slot) with the JSONL-derived
11
+ // prediction. Used by the /usage burndown overlay and by the Calibration
12
+ // Check chart.
13
+ export type CalibrationPoint = {
14
+ ts: string;
15
+ real_5h: number | null;
16
+ pred_5h: number;
17
+ real_7d: number | null;
18
+ pred_7d: number;
19
+ /** ISO `resets_at` for the cycle this point belongs to. Lets the
20
+ * summary helper bucket points into cycles without sniffing for
21
+ * value drops. May be null for cold-start back-fill that lands
22
+ * before any known reset. */
23
+ cycle_end_5h?: string | null;
24
+ cycle_end_7d?: string | null;
25
+ };
26
+
27
+ export type CalibrationDump = {
28
+ curve: CalibrationPoint[];
29
+ // Older Python dumps had per-feature coefficients; the $-rate predictor
30
+ // doesn't, so these are optional. Kept around so existing chart code
31
+ // that may inspect them doesn't crash on undefined.
32
+ coefs_5h?: number[];
33
+ coefs_7d?: number[];
34
+ rate_per_pct?: number;
35
+ rate_per_pct_5h?: number;
36
+ rate_per_pct_7d?: number;
37
+ rate_source_5h?: RateSource;
38
+ rate_source_7d?: RateSource;
39
+ cycles_used_5h?: number;
40
+ cycles_used_7d?: number;
41
+ tier?: string;
42
+ };
43
+
44
+ export type PredictedSeriesByKey = {
45
+ five_hour: { capturedAt: number; util: number }[];
46
+ seven_day: { capturedAt: number; util: number }[];
47
+ seven_day_sonnet: { capturedAt: number; util: number }[];
48
+ };
49
+
50
+ // History of recent cycles for trend visuals. Each entry is one full cycle
51
+ // the user lived through — `current: true` flags the live (in-progress)
52
+ // cycle, the rest are completed. `source: "real"` = daemon observed the
53
+ // peak, `source: "predicted"` = cycle predates daemon data and we fall
54
+ // back to the JSONL-derived prediction (cold-start path).
55
+ export type CyclePeak = {
56
+ endsAt: string;
57
+ peakPct: number;
58
+ source: "real" | "predicted";
59
+ current: boolean;
60
+ };
61
+
62
+ // Per-cycle peak history for a single window (5h or 7d). Used by the
63
+ // dashboard's "previous cycles" trend strip — humans understand "last 4
64
+ // weeks: 86%, 92%, 44%, 34% (current)" much better than a single number.
65
+ // Limited to the last `maxCycles` (most recent) so the visual stays compact.
66
+ export function previousCyclesTrend(
67
+ dump: CalibrationDump | null,
68
+ window: "5h" | "7d",
69
+ maxCycles = 6,
70
+ ): CyclePeak[] {
71
+ if (!dump || dump.curve.length < 2) return [];
72
+ const HOUR = 3_600_000;
73
+ const cycleKey: "cycle_end_5h" | "cycle_end_7d" = window === "5h" ? "cycle_end_5h" : "cycle_end_7d";
74
+ const predKey: "pred_5h" | "pred_7d" = window === "5h" ? "pred_5h" : "pred_7d";
75
+ const realKey: "real_5h" | "real_7d" = window === "5h" ? "real_5h" : "real_7d";
76
+
77
+ // Hour-round the cycle key so millisecond-jittered resets collapse.
78
+ const byCycle = new Map<number, typeof dump.curve>();
79
+ for (const p of dump.curve) {
80
+ const k = p[cycleKey];
81
+ if (!k) continue;
82
+ const ms = Date.parse(k);
83
+ if (Number.isNaN(ms)) continue;
84
+ const bucket = Math.round(ms / HOUR) * HOUR;
85
+ const arr = byCycle.get(bucket) ?? [];
86
+ arr.push(p);
87
+ byCycle.set(bucket, arr);
88
+ }
89
+
90
+ const nowMs = Date.now();
91
+ const cycles: CyclePeak[] = [];
92
+ for (const [endMs, points] of Array.from(byCycle.entries()).sort((a, b) => a[0] - b[0])) {
93
+ // Take the max across BOTH real and predicted — when the daemon goes
94
+ // dark before cycle close, predicted forward-extrapolation often
95
+ // exceeds the last observed value, and the cycle's true peak is the
96
+ // predicted close, not the last poll. `source` reflects which side won.
97
+ let peak = 0;
98
+ let source: "real" | "predicted" = "predicted";
99
+ for (const p of points) {
100
+ const r = p[realKey];
101
+ if (typeof r === "number" && r > peak) { peak = r; source = "real"; }
102
+ const v = p[predKey] ?? 0;
103
+ if (v > peak) { peak = v; source = "predicted"; }
104
+ }
105
+ cycles.push({
106
+ endsAt: new Date(endMs).toISOString(),
107
+ peakPct: Math.round(peak * 10) / 10,
108
+ source,
109
+ current: endMs > nowMs,
110
+ });
111
+ }
112
+ return cycles.slice(-maxCycles);
113
+ }
114
+
115
+ // Converts the calibration dump into the same shape UsageChart expects to
116
+ // overlay on each burndown plot. seven_day_sonnet has no predictor today
117
+ // so it returns empty — the chart will simply not show an estimate line.
118
+ export function predictedSeriesFor(dump: CalibrationDump | null): PredictedSeriesByKey {
119
+ if (!dump) return { five_hour: [], seven_day: [], seven_day_sonnet: [] };
120
+ const five_hour = dump.curve
121
+ .filter((c) => Number.isFinite(c.pred_5h))
122
+ .map((c) => ({ capturedAt: new Date(c.ts).getTime(), util: Math.max(0, c.pred_5h) }));
123
+ const seven_day = dump.curve
124
+ .filter((c) => Number.isFinite(c.pred_7d))
125
+ .map((c) => ({ capturedAt: new Date(c.ts).getTime(), util: Math.max(0, c.pred_7d) }));
126
+ return { five_hour, seven_day, seven_day_sonnet: [] };
127
+ }
128
+
129
+ // Default tier when we can't infer the user's subscription from anywhere.
130
+ // /api/oauth/profile auto-detects this on each daemon push but for cold
131
+ // start we fall back to the heaviest tier so cold-start back-fill predicts
132
+ // the longest possible windows. The profile cache lives next to the JSON
133
+ // dump and is read below if available.
134
+ const PROFILE_CACHE = join(homedir(), ".cclens", "profile.json");
135
+ const DEFAULT_TIER: PlanTier = "pro-max-20x";
136
+
137
+ function readTier(): PlanTier {
138
+ if (!existsSync(PROFILE_CACHE)) return DEFAULT_TIER;
139
+ try {
140
+ const raw = JSON.parse(readFileSync(PROFILE_CACHE, "utf8"));
141
+ // Cache shape from writeCachedProfile: { fetchedAtMs, profile: { planTier, ... } }.
142
+ const t = raw?.profile?.planTier as PlanTier | undefined;
143
+ if (t === "pro" || t === "pro-max" || t === "pro-max-20x" || t === "custom") return t;
144
+ } catch {
145
+ /* ignore — fall back to default */
146
+ }
147
+ return DEFAULT_TIER;
148
+ }
149
+
150
+ // Computed live from JSONL transcripts + ~/.cclens/usage.jsonl, replacing
151
+ // the Python sidecar that previously wrote ~/.cclens/calibration-debug.json.
152
+ // The walk is heavy on first call but cached at multiple levels (parser's
153
+ // mtime cache + React's per-request `cache()`).
154
+ export const readCalibrationDump = cache(
155
+ async (): Promise<CalibrationDump | null> => {
156
+ const tier = readTier();
157
+ const result = await loadCalibrationCurve(tier);
158
+ if (!result) return null;
159
+ return {
160
+ curve: result.curve,
161
+ rate_per_pct: result.rate_per_pct,
162
+ rate_per_pct_5h: result.rate_per_pct_5h,
163
+ rate_per_pct_7d: result.rate_per_pct_7d,
164
+ rate_source_5h: result.rate_source_5h,
165
+ rate_source_7d: result.rate_source_7d,
166
+ cycles_used_5h: result.cycles_used_5h,
167
+ cycles_used_7d: result.cycles_used_7d,
168
+ tier: result.tier,
169
+ };
170
+ },
171
+ );
@@ -0,0 +1,174 @@
1
+ import "server-only";
2
+ import { statSync, existsSync, readdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import {
6
+ entriesDir,
7
+ listEntryKeys,
8
+ readEntry,
9
+ readDayDigest,
10
+ } from "@claude-lens/entries/fs";
11
+ import type { Entry, DayOutcome, DayHelpfulness, DayDigest } from "@claude-lens/entries";
12
+ import { canonicalProjectName } from "@claude-lens/parser";
13
+ import { outcomePriority } from "@/components/outcome-pill";
14
+
15
+ export type EntriesIndex = {
16
+ bySession: Map<string, Entry[]>;
17
+ byDay: Map<string, Entry[]>;
18
+ byProject: Map<string, Entry[]>;
19
+ sessionOutcome: Map<string, DayOutcome | null>;
20
+ dayOutcome: Map<string, DayOutcome | null>;
21
+ /** Compact slice for the live-sessions widget — no full entries needed. */
22
+ enrichmentStatusBySession: Map<string, Entry["enrichment"]["status"]>;
23
+ };
24
+
25
+ const EMPTY_INDEX: EntriesIndex = {
26
+ bySession: new Map(),
27
+ byDay: new Map(),
28
+ byProject: new Map(),
29
+ sessionOutcome: new Map(),
30
+ dayOutcome: new Map(),
31
+ enrichmentStatusBySession: new Map(),
32
+ };
33
+
34
+ let cache: { mtimeMs: number; index: EntriesIndex } | null = null;
35
+
36
+ function dirMtime(): number {
37
+ const dir = entriesDir();
38
+ if (!existsSync(dir)) return 0;
39
+ return statSync(dir).mtimeMs;
40
+ }
41
+
42
+ export function rollupOutcome(entries: Entry[]): DayOutcome | null {
43
+ let best: DayOutcome | null = null;
44
+ let bestPri = 0;
45
+ for (const e of entries) {
46
+ const o = e.enrichment.outcome ?? null;
47
+ if (!o) continue;
48
+ const pri = outcomePriority(o);
49
+ if (pri > bestPri) {
50
+ bestPri = pri;
51
+ best = o;
52
+ }
53
+ }
54
+ return best;
55
+ }
56
+
57
+ export async function buildEntriesIndex(): Promise<EntriesIndex> {
58
+ const mtime = dirMtime();
59
+ if (mtime === 0) return EMPTY_INDEX;
60
+ if (cache && cache.mtimeMs === mtime) return cache.index;
61
+
62
+ const bySession = new Map<string, Entry[]>();
63
+ const byDay = new Map<string, Entry[]>();
64
+ const byProject = new Map<string, Entry[]>();
65
+ const enrichmentStatusBySession = new Map<string, Entry["enrichment"]["status"]>();
66
+
67
+ for (const key of listEntryKeys()) {
68
+ const sep = key.lastIndexOf("__");
69
+ if (sep === -1) continue;
70
+ const sessionId = key.slice(0, sep);
71
+ const localDay = key.slice(sep + 2);
72
+ const e = readEntry(sessionId, localDay);
73
+ if (!e) continue;
74
+
75
+ const list = bySession.get(e.session_id);
76
+ if (list) list.push(e); else bySession.set(e.session_id, [e]);
77
+
78
+ const dlist = byDay.get(e.local_day);
79
+ if (dlist) dlist.push(e); else byDay.set(e.local_day, [e]);
80
+
81
+ const canonical = canonicalProjectName(e.project);
82
+ const plist = byProject.get(canonical);
83
+ if (plist) plist.push(e); else byProject.set(canonical, [e]);
84
+
85
+ // Most recent enrichment status wins for the session-level summary
86
+ const cur = enrichmentStatusBySession.get(e.session_id);
87
+ if (!cur || cur === "pending" || cur === "error") {
88
+ enrichmentStatusBySession.set(e.session_id, e.enrichment.status);
89
+ }
90
+ }
91
+
92
+ // Sort each session's entries by local_day asc
93
+ for (const list of bySession.values()) {
94
+ list.sort((a, b) => a.local_day.localeCompare(b.local_day));
95
+ }
96
+
97
+ const sessionOutcome = new Map<string, DayOutcome | null>();
98
+ for (const [sid, entries] of bySession) {
99
+ sessionOutcome.set(sid, rollupOutcome(entries));
100
+ }
101
+
102
+ const dayOutcome = new Map<string, DayOutcome | null>();
103
+ for (const [day, entries] of byDay) {
104
+ dayOutcome.set(day, rollupOutcome(entries));
105
+ }
106
+
107
+ const index: EntriesIndex = {
108
+ bySession,
109
+ byDay,
110
+ byProject,
111
+ sessionOutcome,
112
+ dayOutcome,
113
+ enrichmentStatusBySession,
114
+ };
115
+ cache = { mtimeMs: mtime, index };
116
+ return index;
117
+ }
118
+
119
+ /* ============================================================ */
120
+ /* Day-digest cache lookups (separate, lighter cache) */
121
+ /* ============================================================ */
122
+
123
+ export type DayDigestSummary = {
124
+ date: string;
125
+ headline: string | null;
126
+ outcome_day: DayOutcome | null;
127
+ helpfulness_day: DayHelpfulness;
128
+ agent_min: number;
129
+ shipped_count: number;
130
+ };
131
+
132
+ let digestCache: { mtimeMs: number; map: Map<string, DayDigestSummary> } | null = null;
133
+
134
+ function digestsDir(): string {
135
+ return process.env.CCLENS_DIGESTS_DIR ?? join(homedir(), ".cclens", "digests", "day");
136
+ }
137
+
138
+ function digestsDirMtime(): number {
139
+ const d = digestsDir();
140
+ if (!existsSync(d)) return 0;
141
+ return statSync(d).mtimeMs;
142
+ }
143
+
144
+ export async function listCachedDayDigests(): Promise<Map<string, DayDigestSummary>> {
145
+ const mtime = digestsDirMtime();
146
+ if (mtime === 0) return new Map();
147
+ if (digestCache && digestCache.mtimeMs === mtime) return digestCache.map;
148
+
149
+ const dir = digestsDir();
150
+ const out = new Map<string, DayDigestSummary>();
151
+ for (const f of readdirSync(dir)) {
152
+ if (!f.endsWith(".json")) continue;
153
+ const date = f.slice(0, -".json".length);
154
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) continue;
155
+ const d: DayDigest | null = readDayDigest(date);
156
+ if (!d) continue;
157
+ out.set(date, {
158
+ date,
159
+ headline: d.headline,
160
+ outcome_day: d.outcome_day,
161
+ helpfulness_day: d.helpfulness_day,
162
+ agent_min: d.agent_min,
163
+ shipped_count: d.shipped.length,
164
+ });
165
+ }
166
+ digestCache = { mtimeMs: mtime, map: out };
167
+ return out;
168
+ }
169
+
170
+ /** Reset both caches — test-only escape hatch. */
171
+ export function __resetEntriesIndexCacheForTest(): void {
172
+ cache = null;
173
+ digestCache = null;
174
+ }
@@ -0,0 +1,72 @@
1
+ import "server-only";
2
+
3
+ export { listEntriesForDay, readDayDigest, writeDayDigest } from "@claude-lens/entries/fs";
4
+
5
+ export function toLocalDay(ms: number): string {
6
+ const d = new Date(ms);
7
+ const y = d.getFullYear();
8
+ const m = String(d.getMonth() + 1).padStart(2, "0");
9
+ const day = String(d.getDate()).padStart(2, "0");
10
+ return `${y}-${m}-${day}`;
11
+ }
12
+
13
+ export function yesterdayLocal(nowMs: number = Date.now()): string {
14
+ return toLocalDay(nowMs - 86_400_000);
15
+ }
16
+
17
+ export function todayLocal(nowMs: number = Date.now()): string {
18
+ return toLocalDay(nowMs);
19
+ }
20
+
21
+ const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
22
+ export function isValidDate(s: string): boolean {
23
+ return DATE_RE.test(s);
24
+ }
25
+
26
+ const YEAR_MONTH_RE = /^\d{4}-\d{2}$/;
27
+ export function isValidYearMonth(s: string): boolean {
28
+ return YEAR_MONTH_RE.test(s);
29
+ }
30
+
31
+ /** Monday of the ISO week containing localDay (Mon-Sun, server local TZ). */
32
+ export function mondayOf(localDay: string): string {
33
+ const d = new Date(`${localDay}T00:00:00`);
34
+ const dow = d.getDay();
35
+ const offset = dow === 0 ? -6 : 1 - dow;
36
+ d.setDate(d.getDate() + offset);
37
+ return toLocalDay(d.getTime());
38
+ }
39
+
40
+ export function currentWeekMonday(nowMs: number = Date.now()): string {
41
+ return mondayOf(todayLocal(nowMs));
42
+ }
43
+
44
+ /** Most recent COMPLETED week — last week's Monday. */
45
+ export function lastCompletedWeekMonday(nowMs: number = Date.now()): string {
46
+ const thisMonday = currentWeekMonday(nowMs);
47
+ const d = new Date(`${thisMonday}T00:00:00`);
48
+ d.setDate(d.getDate() - 7);
49
+ return toLocalDay(d.getTime());
50
+ }
51
+
52
+ export function currentYearMonth(nowMs: number = Date.now()): string {
53
+ const today = todayLocal(nowMs);
54
+ return today.slice(0, 7);
55
+ }
56
+
57
+ export function lastCompletedMonth(nowMs: number = Date.now()): string {
58
+ const today = todayLocal(nowMs);
59
+ const [y, m] = today.split("-");
60
+ const yi = Number(y);
61
+ const mi = Number(m);
62
+ if (mi === 1) return `${yi - 1}-12`;
63
+ return `${yi}-${String(mi - 1).padStart(2, "0")}`;
64
+ }
65
+
66
+ /** Validates and returns the Monday for `s` if `s` is itself a Monday in YYYY-MM-DD form. */
67
+ export function asMonday(s: string): string | null {
68
+ if (!isValidDate(s)) return null;
69
+ const d = new Date(`${s}T00:00:00`);
70
+ if (d.getDay() !== 1) return null;
71
+ return s;
72
+ }
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { InflightCoalescer } from "./inflight-coalesce";
3
+
4
+ describe("InflightCoalescer", () => {
5
+ it("second caller with same key awaits the first; worker runs once", async () => {
6
+ const c = new InflightCoalescer<string, string>();
7
+ let runs = 0;
8
+ const worker = async () => { runs++; await new Promise(r => setTimeout(r, 10)); return "ok"; };
9
+
10
+ const [a, b] = await Promise.all([
11
+ c.run("k1", worker),
12
+ c.run("k1", worker),
13
+ ]);
14
+ expect(a).toBe("ok");
15
+ expect(b).toBe("ok");
16
+ expect(runs).toBe(1);
17
+ });
18
+
19
+ it("different keys run independently", async () => {
20
+ const c = new InflightCoalescer<string, string>();
21
+ let runs = 0;
22
+ const worker = async () => { runs++; return "ok"; };
23
+ await Promise.all([c.run("k1", worker), c.run("k2", worker)]);
24
+ expect(runs).toBe(2);
25
+ });
26
+
27
+ it("drops entry after resolution so subsequent same-key call re-runs", async () => {
28
+ const c = new InflightCoalescer<string, string>();
29
+ let runs = 0;
30
+ const worker = async () => { runs++; return "ok"; };
31
+ await c.run("k1", worker);
32
+ await c.run("k1", worker);
33
+ expect(runs).toBe(2);
34
+ });
35
+
36
+ it("drops entry after rejection and propagates the error", async () => {
37
+ const c = new InflightCoalescer<string, string>();
38
+ const failing = async (): Promise<string> => { throw new Error("boom"); };
39
+ await expect(c.run("k1", failing)).rejects.toThrow("boom");
40
+ const ok = await c.run("k1", async () => "ok");
41
+ expect(ok).toBe("ok");
42
+ });
43
+ });
@@ -0,0 +1,19 @@
1
+ export class InflightCoalescer<K, V> {
2
+ private readonly map = new Map<K, Promise<V>>();
3
+
4
+ async run(key: K, worker: () => Promise<V>): Promise<V> {
5
+ const existing = this.map.get(key);
6
+ if (existing) return existing;
7
+ const p = worker();
8
+ this.map.set(key, p);
9
+ try {
10
+ return await p;
11
+ } finally {
12
+ this.map.delete(key);
13
+ }
14
+ }
15
+
16
+ inflight(key: K): boolean {
17
+ return this.map.has(key);
18
+ }
19
+ }