@zaip-ai/cli 1.0.7 → 1.0.8

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 (410) hide show
  1. package/README.md +6 -4
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.d.ts.map +1 -1
  4. package/dist/services/adapters.js +15 -5
  5. package/dist/services/adapters.js.map +1 -1
  6. package/dist/services/adapters.test.js +1 -1
  7. package/dist/services/agent-adapters.d.ts +9 -0
  8. package/dist/services/agent-adapters.d.ts.map +1 -1
  9. package/dist/services/agent-adapters.js +38 -3
  10. package/dist/services/agent-adapters.js.map +1 -1
  11. package/dist/services/agent-adapters.test.js +8 -1
  12. package/dist/services/agent-adapters.test.js.map +1 -1
  13. package/dist/services/codex-config-template.d.ts +2 -1
  14. package/dist/services/codex-config-template.d.ts.map +1 -1
  15. package/dist/services/codex-config-template.js +13 -2
  16. package/dist/services/codex-config-template.js.map +1 -1
  17. package/dist/services/codex-rules.d.ts +1 -1
  18. package/dist/services/codex-rules.d.ts.map +1 -1
  19. package/dist/services/codex-rules.js +31 -7
  20. package/dist/services/codex-rules.js.map +1 -1
  21. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  22. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  23. package/dist/services/codex-subagent-hook-template.js +4 -1
  24. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  25. package/dist/services/doctor.d.ts.map +1 -1
  26. package/dist/services/doctor.js +3 -1
  27. package/dist/services/doctor.js.map +1 -1
  28. package/dist/services/global-codex-config.d.ts +6 -3
  29. package/dist/services/global-codex-config.d.ts.map +1 -1
  30. package/dist/services/global-codex-config.js +82 -13
  31. package/dist/services/global-codex-config.js.map +1 -1
  32. package/dist/services/global-codex-config.test.js +57 -10
  33. package/dist/services/global-codex-config.test.js.map +1 -1
  34. package/dist/services/install-agents-template.d.ts.map +1 -1
  35. package/dist/services/install-agents-template.js +15 -2
  36. package/dist/services/install-agents-template.js.map +1 -1
  37. package/dist/services/logger.js +1 -1
  38. package/dist/services/logger.js.map +1 -1
  39. package/dist/services/logger.test.js +3 -3
  40. package/dist/services/logger.test.js.map +1 -1
  41. package/dist/services/runtime-template.test.js +21 -5
  42. package/dist/services/runtime-template.test.js.map +1 -1
  43. package/dist/services/template-manifest.d.ts.map +1 -1
  44. package/dist/services/template-manifest.js +2 -0
  45. package/dist/services/template-manifest.js.map +1 -1
  46. package/package.json +1 -1
  47. package/templates/.agents/config/agents/catalog.yaml +310 -10
  48. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +30 -0
  49. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +5 -5
  50. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
  51. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +30 -0
  52. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +30 -0
  53. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +30 -0
  54. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +8 -8
  55. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +5 -3
  56. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +30 -0
  57. package/templates/.agents/config/project.yaml +1 -1
  58. package/templates/.agents/dashboard/.zaip-managed.json +659 -163
  59. package/templates/.agents/dashboard/DATA-DICTIONARY.md +2227 -0
  60. package/templates/.agents/dashboard/README.md +48 -97
  61. package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-Z60df2r-.js +1 -0
  62. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-Cv-JcoxP.js → DashboardHelpDialog-Cs6dzDmW.js} +294 -109
  63. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-Coc6pA-1.js +1 -0
  64. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +1 -0
  65. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +3 -0
  66. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +1 -0
  67. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-CaKwQP43.css +1 -0
  68. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +1 -0
  69. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +68 -0
  70. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-C98LGC-Q.js → dashboard-localization-CLJ0lT9v.js} +1 -1
  71. package/templates/.agents/dashboard/apps/frontend/dist/assets/icons-vendor-DFBuc_qp.js +1 -0
  72. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +2 -0
  73. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +1 -0
  74. package/templates/.agents/dashboard/apps/frontend/dist/assets/react-vendor-CCQOHdVI.js +9 -0
  75. package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +1 -0
  76. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DFY7ZDlu.css +1 -0
  77. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-pC2_0J8x.js +1 -0
  78. package/templates/.agents/dashboard/apps/frontend/dist/index.html +9 -2
  79. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  80. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +952 -595
  81. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +48 -0
  82. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +2 -0
  83. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +247 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/AppRequestGuards.tsx +95 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/AppSetupRoutes.tsx +87 -0
  86. package/templates/.agents/dashboard/apps/frontend/src/CostCalculationGuidePage.tsx +641 -0
  87. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +159 -0
  88. package/templates/.agents/dashboard/apps/frontend/src/DashboardCapabilityNav.tsx +13 -13
  89. package/templates/.agents/dashboard/apps/frontend/src/DashboardGlobalSettings.tsx +56 -0
  90. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +257 -313
  91. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +149 -0
  92. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +35 -0
  93. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +111 -12
  94. package/templates/.agents/dashboard/apps/frontend/src/app-preferences.ts +15 -0
  95. package/templates/.agents/dashboard/apps/frontend/src/app-session-token.ts +20 -0
  96. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.css +267 -0
  97. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.test.ts +69 -0
  98. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +70 -0
  99. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +111 -0
  100. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +432 -13
  101. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +1 -1
  102. package/templates/.agents/dashboard/apps/frontend/src/main.tsx +1 -0
  103. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.test.ts +55 -0
  104. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.ts +36 -0
  105. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.test.ts +126 -0
  106. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.ts +181 -0
  107. package/templates/.agents/dashboard/apps/frontend/src/operations-period-contract.test.ts +138 -0
  108. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +105 -0
  109. package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +6 -3
  110. package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +9 -5
  111. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +24 -0
  112. package/templates/.agents/dashboard/apps/frontend/src/period-transition-overlay.css +44 -0
  113. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +121 -62
  114. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +471 -2
  115. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +84 -17
  116. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +44 -0
  117. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +196 -39
  118. package/templates/.agents/dashboard/apps/frontend/src/snapshot-notice.ts +15 -0
  119. package/templates/.agents/dashboard/apps/frontend/src/sqlite-cost-adapters.ts +26 -0
  120. package/templates/.agents/dashboard/apps/frontend/src/styles.css +14 -2
  121. package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +38 -2
  122. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +187 -0
  123. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +190 -0
  124. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +121 -0
  125. package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +398 -0
  126. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +141 -0
  127. package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +45 -0
  128. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +46 -0
  129. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +37 -0
  130. package/templates/.agents/dashboard/apps/frontend/vite.config.ts +55 -5
  131. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  132. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +47 -6
  133. package/templates/.agents/dashboard/modules/cost-monitor/src/duration-estimate.ts +13 -0
  134. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +64 -0
  135. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +275 -0
  136. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +100 -15
  137. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +131 -40
  138. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +137 -19
  139. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.test.ts +2 -0
  140. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +13 -10
  141. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +303 -0
  142. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +226 -6
  143. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +479 -402
  144. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostSummary.tsx +5 -13
  145. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +312 -72
  146. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +373 -321
  147. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.test.ts +17 -0
  148. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.tsx +25 -6
  149. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +0 -2
  150. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-helpers.ts +17 -0
  151. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-responsive.css +6 -3
  152. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-row-filters.ts +123 -0
  153. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +8 -3
  154. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +32 -0
  155. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +52 -14
  156. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +121 -0
  157. package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +3 -0
  158. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.test.ts +68 -0
  159. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +32 -5
  160. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +108 -0
  161. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +12 -0
  162. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +60 -0
  163. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +106 -0
  164. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.test.ts +2 -2
  165. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.ts +5 -3
  166. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-pricing-fallback.test.ts +53 -0
  167. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.basics.test.ts +34 -0
  168. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +168 -137
  169. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +188 -29
  170. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +956 -0
  171. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +775 -0
  172. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +95 -0
  173. package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
  174. package/templates/.agents/dashboard/modules/cost-monitor/src/server/refactor-map-xr9l.json +61 -0
  175. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.test.ts +41 -0
  176. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.ts +55 -11
  177. package/templates/.agents/dashboard/modules/operations/package.json +2 -1
  178. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +182 -0
  179. package/templates/.agents/dashboard/modules/operations/src/duration-population.test.ts +63 -1
  180. package/templates/.agents/dashboard/modules/operations/src/duration-population.ts +60 -5
  181. package/templates/.agents/dashboard/modules/operations/src/react/EntityDetailsDialog.tsx +14 -3
  182. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.test.ts +44 -1
  183. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +325 -18
  184. package/templates/.agents/dashboard/modules/operations/src/react/MacroPlanningDialog.tsx +1 -0
  185. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.test.ts +9 -5
  186. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.tsx +2 -2
  187. package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +168 -0
  188. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +95 -6
  189. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +365 -14
  190. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +532 -131
  191. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +314 -358
  192. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +68 -0
  193. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +169 -0
  194. package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +51 -8
  195. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +32 -0
  196. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.tsx +62 -6
  197. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.test.ts +55 -0
  198. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.tsx +27 -19
  199. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +99 -42
  200. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +19 -0
  201. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +255 -34
  202. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +163 -8
  203. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +101 -68
  204. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.test.ts +72 -1
  205. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +78 -16
  206. package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +6 -4
  207. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +50 -1
  208. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +143 -9
  209. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +29 -4
  210. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog-content.css +49 -0
  211. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog.css +93 -50
  212. package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +82 -0
  213. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.test.ts +29 -2
  214. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.ts +22 -1
  215. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +77 -4
  216. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +65 -5
  217. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +54 -0
  218. package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +19 -0
  219. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +149 -12
  220. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +27 -0
  221. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +136 -0
  222. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.test.ts +160 -0
  223. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.ts +47 -0
  224. package/templates/.agents/dashboard/modules/operations/src/react/operations-query.ts +10 -0
  225. package/templates/.agents/dashboard/modules/operations/src/react/operations-responsive.css +3 -0
  226. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-labels.ts +28 -0
  227. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +24 -7
  228. package/templates/.agents/dashboard/modules/operations/src/react/operations.css +42 -0
  229. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.test.ts +54 -0
  230. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.ts +32 -0
  231. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +165 -6
  232. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +148 -6
  233. package/templates/.agents/dashboard/modules/operations/src/react/popup-localization.test.ts +1 -1
  234. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css +132 -0
  235. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css.test.ts +13 -0
  236. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.header.test.ts +16 -0
  237. package/templates/.agents/dashboard/modules/operations/src/react/use-infinite-column.ts +11 -5
  238. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +5 -3
  239. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +4 -83
  240. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.test.ts +291 -15
  241. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.ts +182 -472
  242. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.test.ts +40 -0
  243. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.ts +19 -6
  244. package/templates/.agents/dashboard/modules/operations/src/server/canonical-run-projection.ts +31 -6
  245. package/templates/.agents/dashboard/modules/operations/src/server/daily-duration-projection.ts +220 -0
  246. package/templates/.agents/dashboard/modules/operations/src/server/execution-duration-projection.ts +28 -0
  247. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +27 -2
  248. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +22 -13
  249. package/templates/.agents/dashboard/modules/operations/src/server/filter.test.ts +3 -3
  250. package/templates/.agents/dashboard/modules/operations/src/server/filter.ts +7 -2
  251. package/templates/.agents/dashboard/modules/operations/src/server/index.ts +3 -0
  252. package/templates/.agents/dashboard/modules/operations/src/server/macro.ts +3 -12
  253. package/templates/.agents/dashboard/modules/operations/src/server/manifest-usage.ts +65 -0
  254. package/templates/.agents/dashboard/modules/operations/src/server/operations-projection-aggregates.ts +297 -0
  255. package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +324 -0
  256. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.test.ts +505 -0
  257. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.ts +609 -0
  258. package/templates/.agents/dashboard/modules/operations/src/server/runs.ts +18 -19
  259. package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +76 -0
  260. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  261. package/templates/.agents/dashboard/modules/traceability/src/server/build-task-trace.ts +3 -1
  262. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  263. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  264. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  265. package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
  266. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  267. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1756 -0
  268. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1608 -0
  269. package/templates/.agents/dashboard/packages/local-runtime/package.json +8 -3
  270. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +12 -0
  271. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +83 -0
  272. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +28 -0
  273. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +262 -0
  274. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +41 -0
  275. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +105 -0
  276. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1643 -107
  277. package/templates/.agents/dashboard/packages/local-runtime/src/agent-adapter-sync.ts +30 -0
  278. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +3 -2
  279. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.ts +5 -0
  280. package/templates/.agents/dashboard/packages/local-runtime/src/manifest-runs.ts +72 -33
  281. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +335 -4
  282. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +392 -1
  283. package/templates/.agents/dashboard/packages/local-runtime/src/runtime.mjs +5 -5
  284. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +71 -0
  285. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +179 -0
  286. package/templates/.agents/dashboard/packages/local-runtime/src/server-cross-layer-parity.test.ts +245 -0
  287. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models-route.ts +64 -0
  288. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.test.ts +204 -0
  289. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.ts +194 -0
  290. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.test.ts +163 -0
  291. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.ts +354 -0
  292. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.test.ts +74 -0
  293. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.ts +113 -0
  294. package/templates/.agents/dashboard/packages/local-runtime/src/server-overview.test.ts +68 -0
  295. package/templates/.agents/dashboard/packages/local-runtime/src/server-period.ts +47 -0
  296. package/templates/.agents/dashboard/packages/local-runtime/src/server-projections.ts +483 -0
  297. package/templates/.agents/dashboard/packages/local-runtime/src/server-settings.test.ts +5 -2
  298. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +163 -84
  299. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +145 -0
  300. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +551 -266
  301. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +1145 -308
  302. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +53 -0
  303. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +708 -0
  304. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +2232 -0
  305. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +6151 -0
  306. package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +33 -0
  307. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-history.mjs +41 -0
  308. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-processes.mjs +210 -0
  309. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +437 -190
  310. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +299 -24
  311. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  312. package/templates/.agents/dashboard/packages/windows-launcher/LauncherVerificationBehaviorTests.cs +206 -0
  313. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +95 -8
  314. package/templates/.agents/dashboard/packages/windows-launcher/build-dashboard-launcher.ps1 +2 -2
  315. package/templates/.agents/dashboard/packages/windows-launcher/run-launcher-verification-tests.ps1 +22 -0
  316. package/templates/.agents/dashboard/read-model.dbml +2201 -0
  317. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  318. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +1 -1
  319. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +214 -41
  320. package/templates/.agents/dashboard/work-priority.json +34 -0
  321. package/templates/.agents/dashboard/zaip-dashboard-linux.sh +45 -0
  322. package/templates/.agents/dashboard/zaip-dashboard-mac.command +3 -0
  323. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  324. package/templates/.agents/design/.zaip-managed.json +3 -3
  325. package/templates/.agents/design/apps/catalog/package.json +1 -1
  326. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  327. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  328. package/templates/.agents/requirements/comparative-audit.md +1 -1
  329. package/templates/.agents/requirements/context-engine.md +1 -1
  330. package/templates/.agents/requirements/cost-observability.md +1 -1
  331. package/templates/.agents/requirements/dashboard-launch.md +24 -0
  332. package/templates/.agents/requirements/data-export.md +1 -1
  333. package/templates/.agents/requirements/design-system.md +1 -1
  334. package/templates/.agents/requirements/execution-engine.md +1 -1
  335. package/templates/.agents/requirements/kanban-dashboard.md +4 -3
  336. package/templates/.agents/requirements/model-orchestration.md +1 -1
  337. package/templates/.agents/requirements/public-distribution.md +9 -6
  338. package/templates/.agents/requirements/software-architecture.md +1 -1
  339. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  340. package/templates/.agents/requirements/work-lifecycle.md +9 -3
  341. package/templates/.agents/requirements/zaip-strategic-95.md +4 -4
  342. package/templates/.agents/rules/autonomy-decision.md +15 -0
  343. package/templates/.agents/rules/core.md +1 -1
  344. package/templates/.agents/rules/run-lifecycle-closure.md +1 -1
  345. package/templates/.agents/rules/specialist-routing.md +19 -0
  346. package/templates/.agents/rules/workflow.md +1 -1
  347. package/templates/.agents/runtime/VERSION +1 -1
  348. package/templates/.agents/runtime/bin/zaip.mjs +114 -64
  349. package/templates/.agents/runtime/checksums.sha256 +6 -4
  350. package/templates/.agents/runtime/manifest.json +3 -1
  351. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -0
  352. package/templates/.agents/runtime/provenance.json +11 -0
  353. package/templates/.agents/runtime/sbom.cdx.json +1929 -39
  354. package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
  355. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +15 -0
  356. package/templates/.agents/skills/zaip-skill-brand-governance/agents/openai.yaml +4 -0
  357. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +30 -0
  358. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +25 -0
  359. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/agents/openai.yaml +4 -0
  360. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +18 -0
  361. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/agents/openai.yaml +6 -0
  362. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +71 -0
  363. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +60 -0
  364. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +111 -0
  365. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +2 -2
  366. package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +3 -1
  367. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +12 -0
  368. package/templates/.agents/skills/zaip-skill-general-operations/agents/openai.yaml +4 -0
  369. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +9 -7
  370. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  371. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +11 -38
  372. package/templates/.agents/skills/zaip-skill-governance-compliance/SKILL.md +12 -0
  373. package/templates/.agents/skills/zaip-skill-governance-compliance/agents/openai.yaml +4 -0
  374. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +15 -0
  375. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/agents/openai.yaml +4 -0
  376. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/references/growth-revops-framework.md +25 -0
  377. package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +17 -0
  378. package/templates/.agents/skills/zaip-skill-instalar-agendamento/agents/openai.yaml +6 -0
  379. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +3 -3
  380. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +76 -27
  381. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +128 -24
  382. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +122 -4
  383. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +66 -19
  384. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +193 -7
  385. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +14 -0
  386. package/templates/.agents/skills/zaip-skill-sales-methodology/agents/openai.yaml +4 -0
  387. package/templates/.agents/skills/zaip-skill-sales-methodology/references/sales-process-framework.md +77 -0
  388. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +5 -0
  389. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +96 -0
  390. package/templates/.agents/skills/zaip-skill-sqlite-read-model/agents/openai.yaml +4 -0
  391. package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +18 -0
  392. package/templates/.agents/zaip-aios/INDEX.md +1 -0
  393. package/templates/.agents/zaip-aios/README.md +37 -8
  394. package/templates/.agents/zaip-aios/VERSION +1 -1
  395. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +43 -6
  396. package/templates/.agents/zaip-aios/guides/10-seguranca.md +21 -7
  397. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +32 -0
  398. package/templates/template-manifest.json +945 -214
  399. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-CLYIi7Vo.js +0 -1
  400. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-DTDNVQGX.css +0 -1
  401. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-CzEggcRb.js +0 -1
  402. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-05YKn6Z4.js +0 -3
  403. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-YO3yqtgV.css +0 -1
  404. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8AzCnl3a.js +0 -77
  405. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DdBYQ_8D.css +0 -1
  406. package/templates/.agents/dashboard/apps/frontend/src/AgentCatalogSettingsPage.tsx +0 -617
  407. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings-page.css +0 -660
  408. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings.test.ts +0 -249
  409. package/templates/.agents/dashboard/dashboard.config.json +0 -4
  410. package/templates/.agents/dashboard/zaip-dashboard.exe +0 -0
@@ -0,0 +1,956 @@
1
+ import {
2
+ globalLegacyEffortDurationMs,
3
+ type OperationsProjection,
4
+ } from "@zaip-ai/dashboard-operations/contracts";
5
+ import { describe, expect, it } from "vitest";
6
+ import {
7
+ buildCostSummaryProjection,
8
+ type CostSummarySource,
9
+ } from "./build-cost-summary-projection.js";
10
+
11
+ describe("buildCostSummaryProjection", () => {
12
+ it("retains factual USD from a compact SQLite summary with no Run rows", () => {
13
+ const operations = {
14
+ schema_version: 2, layout_version: 2, readonly: true, source: ".agents/records",
15
+ filters: { from: null, to: null }, summary: { task_count: 1, overview_metrics: {}, usage: {} },
16
+ prds: [], specs: [], runs: [],
17
+ } as unknown as OperationsProjection;
18
+ const projection = buildCostSummaryProjection({
19
+ periods: { daily: {
20
+ "2026-08-19": {
21
+ prds: 0, specs: 0, tasks: 1, validations: 0, evidences: 0, runs: 1,
22
+ usage: {
23
+ total_tokens: { known_sum: 100, unknown: 0, complete: true, coverage_ratio: 1 },
24
+ cost: { known_sum: 47.5, unknown: 0, complete: true, coverage_ratio: 1, currency: "BRL" },
25
+ },
26
+ },
27
+ } },
28
+ daily_rows: [{ key: "2026-08-19", total_cost_usd: 8.7, total_cost_brl: 47.5 }],
29
+ cost_monitor_daily_duration: {
30
+ "2026-08-19": { known_sum: 60_000, eligible_runs: 1, known_runs: 1 },
31
+ },
32
+ }, operations, "USD", null);
33
+
34
+ expect(projection).toMatchObject({
35
+ aggregate_only: true,
36
+ runs: [],
37
+ overview: { estimated_usd: 8.7, estimated_brl: 47.5 },
38
+ });
39
+ expect(projection.groups.daily[0]).toMatchObject({ estimated_usd: 8.7, estimated_brl: 47.5 });
40
+ });
41
+
42
+ it("prefers aggregate SQL usage without transporting Run facts", () => {
43
+ const metric = (total: number) => ({
44
+ events: 1,
45
+ duration_ms: total,
46
+ tokens: { input: total, cached_input: total / 2, output: total / 4, reasoning: total / 8, total: total + total / 4 },
47
+ cost: { usd: total / 100, brl: total / 20 },
48
+ coverage: { events: 1, tokens: 1, usd: 1, brl: 1 },
49
+ });
50
+ const aggregate = {
51
+ conversation: metric(10), planning: metric(20), execution: metric(30),
52
+ total: metric(60), new_work: metric(60), rework: metric(0),
53
+ };
54
+ const operations = {
55
+ schema_version: 2, layout_version: 2, readonly: true, source: ".agents/records",
56
+ filters: { from: null, to: null }, summary: { task_count: 0, overview_metrics: {}, usage: {} },
57
+ prds: [], specs: [], runs: [],
58
+ } as unknown as OperationsProjection;
59
+ const projection = buildCostSummaryProjection({
60
+ periods: { daily: {} },
61
+ aggregate_usage: aggregate,
62
+ // Contradictory legacy input proves the aggregate transport wins.
63
+ run_metrics: [{
64
+ id: "LEGACY", started_at: "2026-08-10T12:00:00.000Z", finished_at: null,
65
+ task_id: null, phase: "execution", parent_run_id: null, status: null,
66
+ duration_ms: 999, total_tokens: 999, cost: 999, currency: "BRL", events: 999,
67
+ }],
68
+ }, operations, "BRL", null);
69
+
70
+ expect(projection.usage).toBe(aggregate);
71
+ expect(projection.runs).toEqual([]);
72
+ expect(projection.usage.total.tokens).toMatchObject({ input: 60, cached_input: 30, output: 15, reasoning: 7.5, total: 75 });
73
+ });
74
+
75
+ it("derives phase-aware inclusive usage from compact Run facts when the aggregate transport is empty", () => {
76
+ const run = (id: string, phase: "conversation" | "planning" | "execution", input: number, cached: number, output: number, reasoning: number, cost: number, duration: number) => ({
77
+ id, started_at: "2026-08-10T12:00:00.000Z", finished_at: null, task_id: null,
78
+ phase, parent_run_id: null, status: null, duration_ms: duration, source_duration_ms: duration,
79
+ input_tokens: input, cached_input_tokens: cached, output_tokens: output,
80
+ reasoning_tokens: reasoning, total_tokens: input + output, cost, currency: "BRL", events: 1,
81
+ });
82
+ const summary = {
83
+ periods: { daily: {} },
84
+ run_metrics: [
85
+ run("CONV", "conversation", 10, 4, 5, 2, 1, 100),
86
+ run("PLAN", "planning", 20, 8, 7, 3, 2, 200),
87
+ run("EXEC", "execution", 30, 12, 9, 4, 3, 300),
88
+ ],
89
+ } as CostSummarySource;
90
+ const operations = {
91
+ schema_version: 1, layout_version: 2, readonly: true, source: ".agents/records",
92
+ filters: { from: null, to: null }, summary: { task_count: 0, usage: {} },
93
+ prds: [], specs: [], runs: [],
94
+ } as unknown as OperationsProjection;
95
+
96
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", null);
97
+
98
+ expect(projection.aggregate_only).toBe(true);
99
+ expect(projection.runs).toEqual([]);
100
+ expect(projection.usage.conversation.tokens).toMatchObject({ input: 10, cached_input: 4, output: 5, reasoning: 2, total: 15 });
101
+ expect(projection.usage.planning.tokens).toMatchObject({ input: 20, cached_input: 8, output: 7, reasoning: 3, total: 27 });
102
+ expect(projection.usage.execution.tokens).toMatchObject({ input: 30, cached_input: 12, output: 9, reasoning: 4, total: 39 });
103
+ expect(projection.usage.total.tokens).toMatchObject({ input: 60, cached_input: 24, output: 21, reasoning: 9, total: 81 });
104
+ expect(projection.usage.total.cost.brl).toBe(6);
105
+ expect(projection.usage.total.duration_ms).toBe(600);
106
+ });
107
+
108
+ it("uses segment-backed real model groups for the aggregate-only first fold", () => {
109
+ const operations = {
110
+ schema_version: 2, layout_version: 2, readonly: true, source: ".agents/records",
111
+ filters: { from: null, to: null }, summary: { task_count: 0, overview_metrics: {}, usage: {} }, prds: [], specs: [], runs: [],
112
+ } as unknown as OperationsProjection;
113
+ const group = (key: string, brl: number) => ({
114
+ key, label: key, latest_started_at: "", run_count: 0, task_count: 0,
115
+ prd_count: 0, spec_count: 0, evidence_count: 0, test_count: 0, event_count: 0,
116
+ total_tokens: 1, estimated_usd: brl / 5, estimated_brl: brl, duration_ms: null,
117
+ duration: { known_sum: 0, unknown: 0, complete: true, coverage_ratio: 1 },
118
+ coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
119
+ });
120
+ const projection = buildCostSummaryProjection({
121
+ periods: { daily: {} },
122
+ model_groups: [group("gpt-real", 10), group("claude-real", 5)],
123
+ }, operations, "BRL", null);
124
+
125
+ expect(projection.groups.models.map((row) => [row.key, row.estimated_brl])).toEqual([
126
+ ["gpt-real", 10], ["claude-real", 5],
127
+ ]);
128
+ });
129
+
130
+ it("excludes mixed and unavailable residuals from the model chart", () => {
131
+ const operations = {
132
+ schema_version: 2, layout_version: 2, readonly: true, source: ".agents/records",
133
+ filters: { from: null, to: null }, summary: { task_count: 0, overview_metrics: {}, usage: {} }, prds: [], specs: [], runs: [],
134
+ } as unknown as OperationsProjection;
135
+ const group = (key: string) => ({
136
+ key, label: key, latest_started_at: "", run_count: 0, task_count: null,
137
+ prd_count: 0, spec_count: 0, evidence_count: 0, test_count: 0, event_count: 0,
138
+ total_tokens: 1, estimated_usd: 1, estimated_brl: 5, duration_ms: null,
139
+ duration: { known_sum: 0, unknown: 0, complete: true, coverage_ratio: 1 },
140
+ coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
141
+ });
142
+ const projection = buildCostSummaryProjection({
143
+ periods: { daily: {} },
144
+ model_groups: [group("gpt-real"), group("mixed"), group("unknown"), group("unavailable")],
145
+ }, operations, "BRL", null);
146
+
147
+ expect(projection.groups.models.map((row) => row.key)).toEqual(["gpt-real"]);
148
+ });
149
+
150
+ it("does not promote aggregate token and cost totals without canonical Run facts", () => {
151
+ const known = (known_sum: number, coverage_ratio = 1) => ({
152
+ known_sum,
153
+ unknown: coverage_ratio === 1 ? 0 : 1,
154
+ complete: coverage_ratio === 1,
155
+ coverage_ratio,
156
+ });
157
+ const period = (tasks: number, evidences: number, validations: number, runs: number) => ({
158
+ prds: 0,
159
+ specs: 0,
160
+ tasks,
161
+ validations,
162
+ evidences,
163
+ runs,
164
+ usage: {
165
+ total_tokens: known(tasks * 100),
166
+ cost: { ...known(tasks * 2), currency: "BRL" },
167
+ },
168
+ duration: known(tasks * 1_000),
169
+ events: known(tasks * 3),
170
+ });
171
+ const summary: CostSummarySource = {
172
+ periods: {
173
+ daily: {
174
+ "2026-08-04": period(2, 3, 4, 2),
175
+ "2026-08-05": period(5, 6, 7, 5),
176
+ },
177
+ },
178
+ run_metrics: [
179
+ {
180
+ id: "ROOT-04",
181
+ started_at: "2026-08-04T12:00:00.000Z",
182
+ finished_at: null,
183
+ task_id: null,
184
+ agent: "agent-builder",
185
+ agent_name: "Builder",
186
+ provider: "openai",
187
+ model: "gpt-5.6",
188
+ phase: "execution",
189
+ parent_run_id: null,
190
+ status: null,
191
+ duration_ms: 2_000,
192
+ total_tokens: null,
193
+ cost: null,
194
+ currency: null,
195
+ events: null,
196
+ },
197
+ {
198
+ id: "ROOT-05",
199
+ started_at: "2026-08-05T12:00:00.000Z",
200
+ finished_at: null,
201
+ task_id: null,
202
+ phase: "execution",
203
+ parent_run_id: null,
204
+ status: null,
205
+ duration_ms: 5_000,
206
+ total_tokens: null,
207
+ cost: null,
208
+ currency: null,
209
+ events: null,
210
+ },
211
+ {
212
+ id: "CHILD-05",
213
+ started_at: "2026-08-05T13:00:00.000Z",
214
+ finished_at: null,
215
+ task_id: null,
216
+ phase: "execution",
217
+ parent_run_id: "ROOT-05",
218
+ status: null,
219
+ duration_ms: 99_000,
220
+ total_tokens: null,
221
+ cost: null,
222
+ currency: null,
223
+ events: null,
224
+ },
225
+ ],
226
+ };
227
+ const operations = {
228
+ schema_version: 2,
229
+ layout_version: 2,
230
+ readonly: true,
231
+ source: ".agents/records",
232
+ filters: { from: null, to: null },
233
+ summary: {
234
+ task_count: 7,
235
+ overview_metrics: { task_count: 7 },
236
+ usage: {} as OperationsProjection["summary"]["usage"],
237
+ },
238
+ prds: [],
239
+ specs: [],
240
+ } as unknown as OperationsProjection;
241
+
242
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", 5);
243
+
244
+ expect(projection).toMatchObject({
245
+ aggregate_only: true,
246
+ runs: [],
247
+ overview: {
248
+ task_count: 7,
249
+ run_count: 3,
250
+ event_count: 0,
251
+ total_tokens: null,
252
+ estimated_brl: null,
253
+ },
254
+ });
255
+ expect(projection.groups.agents).toEqual(
256
+ expect.arrayContaining([expect.objectContaining({ label: "Builder" })]),
257
+ );
258
+ expect(projection.groups.providers).toEqual(
259
+ expect.arrayContaining([expect.objectContaining({ label: "openai" })]),
260
+ );
261
+ expect(projection.groups.models).toEqual(
262
+ expect.arrayContaining([expect.objectContaining({ label: "gpt-5.6" })]),
263
+ );
264
+ // High-cardinality lifecycle dimensions are intentionally fetched from
265
+ // their paginated read-model routes only after a user opens that tab.
266
+ expect(projection.groups.conversations).toEqual([]);
267
+ expect(projection.groups.tasks).toEqual([]);
268
+ const filteredDimensions = buildCostSummaryProjection(
269
+ summary,
270
+ { ...operations, filters: { from: "2026-08-05", to: "2026-08-05" } },
271
+ "BRL",
272
+ 5,
273
+ );
274
+ expect(filteredDimensions.groups.daily.reduce((total, row) => total + row.run_count, 0)).toBe(
275
+ 2,
276
+ );
277
+ expect(projection.groups.monthly[0]).toMatchObject({
278
+ key: "2026-08",
279
+ task_count: 7,
280
+ evidence_count: 9,
281
+ test_count: 11,
282
+ duration_ms: 7_000,
283
+ total_tokens: null,
284
+ estimated_brl: null,
285
+ });
286
+ // Effective root timing is not an invocation observation. The phase metric
287
+ // stays unavailable until the SQLite source-duration fact is present.
288
+ expect(projection.usage.execution.duration_ms).toBeNull();
289
+ const firstRun = summary.run_metrics?.[0];
290
+ if (firstRun === undefined) throw new Error("fixture requires a compact Run");
291
+ const observedZero = buildCostSummaryProjection(
292
+ { ...summary, run_metrics: [{ ...firstRun, source_duration_ms: 0 }] },
293
+ operations,
294
+ "BRL",
295
+ 5,
296
+ );
297
+ expect(observedZero.usage.execution.duration_ms).toBe(0);
298
+ });
299
+
300
+ it("derives known token and cost Runs from the filtered period population", () => {
301
+ const summary: CostSummarySource = {
302
+ periods: {
303
+ daily: {
304
+ "2026-08-06": {
305
+ prds: 0,
306
+ specs: 0,
307
+ tasks: 0,
308
+ validations: 0,
309
+ evidences: 0,
310
+ runs: 3,
311
+ usage: {
312
+ total_tokens: { known_sum: 120, unknown: 1, complete: false, coverage_ratio: 2 / 3 },
313
+ cost: {
314
+ known_sum: 4,
315
+ unknown: 1,
316
+ complete: false,
317
+ coverage_ratio: 2 / 3,
318
+ currency: "BRL",
319
+ },
320
+ },
321
+ },
322
+ },
323
+ },
324
+ };
325
+ const operations = {
326
+ filters: { from: null, to: null },
327
+ summary: { task_count: 0 },
328
+ prds: [],
329
+ specs: [],
330
+ } as unknown as OperationsProjection;
331
+ const row = buildCostSummaryProjection(summary, operations, "BRL", 5).groups.daily[0]!;
332
+
333
+ expect(row.coverage_counts).toEqual({
334
+ source: "period_summary",
335
+ granularity: "unavailable",
336
+ events: null,
337
+ tokens: null,
338
+ usd: null,
339
+ brl: null,
340
+ metrics: {
341
+ duration: { eligible_runs: 3, known_runs: 3, unknown_runs: 0 },
342
+ tokens: { eligible_runs: 3, known_runs: 2, unknown_runs: 1 },
343
+ usd: { eligible_runs: 3, known_runs: 2, unknown_runs: 1 },
344
+ brl: { eligible_runs: 3, known_runs: 2, unknown_runs: 1 },
345
+ },
346
+ });
347
+ expect(row.total_tokens).toBe(120);
348
+ expect(row.estimated_brl).toBe(4);
349
+ expect(row.coverage).toEqual({ events: 3, tokens: 2, usd: 2, brl: 2 });
350
+ });
351
+
352
+ it("keeps aggregate-only summary independent from Run-phase dimensions", () => {
353
+ const summary: CostSummarySource = {
354
+ periods: { daily: {} },
355
+ run_metrics: [
356
+ {
357
+ id: "CONVERSATION",
358
+ started_at: "2026-08-07T12:00:00.000Z",
359
+ finished_at: null,
360
+ task_id: null,
361
+ phase: "conversation",
362
+ parent_run_id: null,
363
+ status: null,
364
+ duration_ms: null,
365
+ total_tokens: 10,
366
+ cost: 2,
367
+ currency: "BRL",
368
+ events: 1,
369
+ },
370
+ {
371
+ id: "PLANNING",
372
+ started_at: "2026-08-07T13:00:00.000Z",
373
+ finished_at: null,
374
+ task_id: null,
375
+ phase: "planning",
376
+ parent_run_id: null,
377
+ status: null,
378
+ duration_ms: null,
379
+ total_tokens: 20,
380
+ cost: 3,
381
+ currency: "BRL",
382
+ events: 1,
383
+ },
384
+ {
385
+ id: "EXECUTION",
386
+ started_at: "2026-08-07T14:00:00.000Z",
387
+ finished_at: null,
388
+ task_id: null,
389
+ phase: "execution",
390
+ parent_run_id: null,
391
+ status: null,
392
+ duration_ms: null,
393
+ total_tokens: 30,
394
+ cost: 4,
395
+ currency: "BRL",
396
+ events: 1,
397
+ },
398
+ ],
399
+ };
400
+ const operations = {
401
+ schema_version: 2,
402
+ layout_version: 2,
403
+ readonly: true,
404
+ source: ".agents/records",
405
+ filters: { from: null, to: null },
406
+ summary: { task_count: 0, usage: {} },
407
+ prds: [],
408
+ specs: [],
409
+ tasks: [],
410
+ } as unknown as OperationsProjection;
411
+
412
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", null);
413
+ expect(projection.runs).toEqual([]);
414
+ expect(projection.groups.daily).not.toEqual([]);
415
+ expect(projection.groups.agents).toEqual(
416
+ expect.arrayContaining([expect.objectContaining({ key: "unknown" })]),
417
+ );
418
+ });
419
+
420
+ it("uses the same token-backed effective duration in the fast daily projection", () => {
421
+ const summary: CostSummarySource = {
422
+ periods: {
423
+ daily: {
424
+ "2026-08-07": {
425
+ prds: 0,
426
+ specs: 0,
427
+ tasks: 0,
428
+ validations: 0,
429
+ evidences: 0,
430
+ runs: 1,
431
+ usage: {
432
+ total_tokens: { known_sum: 4_000_000, unknown: 0, complete: true, coverage_ratio: 1 },
433
+ cost: {
434
+ known_sum: 1,
435
+ unknown: 0,
436
+ complete: true,
437
+ coverage_ratio: 1,
438
+ currency: "BRL",
439
+ },
440
+ },
441
+ },
442
+ },
443
+ },
444
+ run_metrics: [
445
+ {
446
+ id: "TOKEN-ONLY",
447
+ started_at: "2026-08-07T12:00:00.000Z",
448
+ finished_at: null,
449
+ task_id: null,
450
+ phase: "execution",
451
+ parent_run_id: null,
452
+ status: null,
453
+ duration_ms: null,
454
+ total_tokens: 4_000_000,
455
+ cost: 1,
456
+ currency: "BRL",
457
+ events: 1,
458
+ },
459
+ ],
460
+ };
461
+ const operations = {
462
+ filters: { from: "2026-08-07", to: "2026-08-07" },
463
+ summary: { task_count: 0 },
464
+ prds: [],
465
+ specs: [],
466
+ } as unknown as OperationsProjection;
467
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", null);
468
+ expect(projection.groups.daily[0]?.duration).toMatchObject({
469
+ known_sum: 3_600_000,
470
+ unknown: 0,
471
+ complete: true,
472
+ });
473
+ });
474
+
475
+ it("enforces positive daily time from period tokens even without compact Run metrics", () => {
476
+ const summary: CostSummarySource = {
477
+ periods: {
478
+ daily: {
479
+ "2026-08-07": {
480
+ prds: 0,
481
+ specs: 0,
482
+ tasks: 0,
483
+ validations: 0,
484
+ evidences: 0,
485
+ runs: 1,
486
+ usage: {
487
+ total_tokens: { known_sum: 4_000_000, unknown: 0, complete: true, coverage_ratio: 1 },
488
+ cost: {
489
+ known_sum: 1,
490
+ unknown: 0,
491
+ complete: true,
492
+ coverage_ratio: 1,
493
+ currency: "BRL",
494
+ },
495
+ },
496
+ },
497
+ },
498
+ },
499
+ };
500
+ const operations = {
501
+ filters: { from: "2026-08-07", to: "2026-08-07" },
502
+ summary: { task_count: 0 },
503
+ prds: [],
504
+ specs: [],
505
+ } as unknown as OperationsProjection;
506
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", null);
507
+ expect(projection.groups.daily[0]).toMatchObject({
508
+ total_tokens: 4_000_000,
509
+ duration_ms: 3_600_000,
510
+ duration: { known_sum: 3_600_000, unknown: 0, complete: true },
511
+ });
512
+ });
513
+
514
+ it("uses the canonical root duration and excludes child and conversation duration", () => {
515
+ const summary: CostSummarySource = {
516
+ periods: {
517
+ daily: {
518
+ "2026-07-24": {
519
+ prds: 0,
520
+ specs: 0,
521
+ tasks: 0,
522
+ validations: 0,
523
+ evidences: 0,
524
+ runs: 3,
525
+ usage: {
526
+ total_tokens: { known_sum: 3, unknown: 0, complete: true, coverage_ratio: 1 },
527
+ cost: {
528
+ known_sum: 3,
529
+ unknown: 0,
530
+ complete: true,
531
+ coverage_ratio: 1,
532
+ currency: "BRL",
533
+ },
534
+ },
535
+ duration: { known_sum: 60_109_200, unknown: 0, complete: true, coverage_ratio: 1 },
536
+ },
537
+ },
538
+ },
539
+ run_metrics: [
540
+ {
541
+ id: "ROOT",
542
+ started_at: "2026-07-24T20:00:00.000Z",
543
+ finished_at: null,
544
+ task_id: null,
545
+ phase: "execution",
546
+ parent_run_id: null,
547
+ status: null,
548
+ duration_ms: 23_241_600,
549
+ total_tokens: 1,
550
+ cost: 1,
551
+ currency: "BRL",
552
+ events: 1,
553
+ },
554
+ {
555
+ id: "CHILD",
556
+ started_at: "2026-07-24T20:01:00.000Z",
557
+ finished_at: null,
558
+ task_id: null,
559
+ phase: "execution",
560
+ parent_run_id: "ROOT",
561
+ status: null,
562
+ duration_ms: 36_867_600,
563
+ total_tokens: 1,
564
+ cost: 1,
565
+ currency: "BRL",
566
+ events: 1,
567
+ },
568
+ {
569
+ id: "CONVERSATION",
570
+ started_at: "2026-07-24T20:02:00.000Z",
571
+ finished_at: null,
572
+ task_id: null,
573
+ phase: "conversation",
574
+ parent_run_id: null,
575
+ status: null,
576
+ duration_ms: 1_000,
577
+ total_tokens: 1,
578
+ cost: 1,
579
+ currency: "BRL",
580
+ events: 1,
581
+ },
582
+ ],
583
+ canonical_daily_duration_ms: { "2026-07-24": 23_241_600 },
584
+ };
585
+ const operations = {
586
+ filters: { from: null, to: null },
587
+ summary: { task_count: 0 },
588
+ prds: [],
589
+ specs: [],
590
+ } as unknown as OperationsProjection;
591
+ const row = buildCostSummaryProjection(summary, operations, "BRL", null).groups.daily.find(
592
+ (value) => value.key === "2026-07-24",
593
+ )!;
594
+
595
+ expect(row.duration.known_sum).toBe(23_241_600);
596
+ expect(row.duration.coverage_ratio).toBe(1);
597
+ expect(row.run_count).toBe(3);
598
+ });
599
+
600
+ it("unions overlapping root execution intervals like Operations", () => {
601
+ const summary: CostSummarySource = {
602
+ periods: {
603
+ daily: {
604
+ "2026-08-07": {
605
+ prds: 0,
606
+ specs: 0,
607
+ tasks: 0,
608
+ validations: 0,
609
+ evidences: 0,
610
+ runs: 2,
611
+ usage: {
612
+ total_tokens: { known_sum: 0, unknown: 2, complete: false, coverage_ratio: 0 },
613
+ cost: {
614
+ known_sum: 0,
615
+ unknown: 2,
616
+ complete: false,
617
+ coverage_ratio: 0,
618
+ currency: "BRL",
619
+ },
620
+ },
621
+ duration: { known_sum: 5_400_000, unknown: 0, complete: true, coverage_ratio: 1 },
622
+ },
623
+ },
624
+ },
625
+ run_metrics: [
626
+ {
627
+ id: "LEFT",
628
+ started_at: "2026-08-07T12:00:00.000Z",
629
+ finished_at: null,
630
+ task_id: null,
631
+ phase: "execution",
632
+ parent_run_id: null,
633
+ status: null,
634
+ duration_ms: 3_600_000,
635
+ duration_started_at: "2026-08-07T12:00:00.000Z",
636
+ total_tokens: null,
637
+ cost: null,
638
+ currency: null,
639
+ events: null,
640
+ },
641
+ {
642
+ id: "RIGHT",
643
+ started_at: "2026-08-07T12:30:00.000Z",
644
+ finished_at: null,
645
+ task_id: null,
646
+ phase: "execution",
647
+ parent_run_id: null,
648
+ status: null,
649
+ duration_ms: 3_600_000,
650
+ duration_started_at: "2026-08-07T12:30:00.000Z",
651
+ total_tokens: null,
652
+ cost: null,
653
+ currency: null,
654
+ events: null,
655
+ },
656
+ ],
657
+ };
658
+ const operations = {
659
+ filters: { from: null, to: null },
660
+ summary: { task_count: 0 },
661
+ prds: [],
662
+ specs: [],
663
+ } as unknown as OperationsProjection;
664
+ expect(
665
+ buildCostSummaryProjection(summary, operations, "BRL", null).groups.daily[0]?.duration
666
+ .known_sum,
667
+ ).toBe(5_400_000);
668
+ });
669
+
670
+ it("keeps canonical root coverage without injecting the legacy baseline", () => {
671
+ const period = (runs: number) => ({
672
+ prds: 0,
673
+ specs: 0,
674
+ tasks: 0,
675
+ validations: 0,
676
+ evidences: 0,
677
+ runs,
678
+ usage: {
679
+ total_tokens: { known_sum: 0, unknown: runs, complete: false, coverage_ratio: 0 },
680
+ cost: { known_sum: 0, unknown: runs, complete: false, coverage_ratio: 0, currency: "BRL" },
681
+ },
682
+ });
683
+ const summary: CostSummarySource = {
684
+ periods: {
685
+ daily: {
686
+ "2026-08-02": {
687
+ ...period(2),
688
+ duration: { known_sum: 2_000, unknown: 0, complete: true, coverage_ratio: 1 },
689
+ },
690
+ "2026-08-03": {
691
+ ...period(1),
692
+ duration: { known_sum: 0, unknown: 1, complete: false, coverage_ratio: 0 },
693
+ },
694
+ },
695
+ },
696
+ run_metrics: [
697
+ {
698
+ id: "PRE",
699
+ started_at: "2026-08-02T03:00:00.000Z",
700
+ finished_at: null,
701
+ task_id: null,
702
+ phase: "execution",
703
+ parent_run_id: null,
704
+ status: null,
705
+ duration_ms: 99_000,
706
+ total_tokens: null,
707
+ cost: null,
708
+ currency: null,
709
+ events: null,
710
+ },
711
+ {
712
+ id: "POST",
713
+ started_at: "2026-08-02T04:00:00.000Z",
714
+ finished_at: null,
715
+ task_id: null,
716
+ phase: "execution",
717
+ parent_run_id: null,
718
+ status: null,
719
+ duration_ms: 2_000,
720
+ total_tokens: null,
721
+ cost: null,
722
+ currency: null,
723
+ events: null,
724
+ },
725
+ {
726
+ id: "UNKNOWN",
727
+ started_at: "2026-08-03T12:00:00.000Z",
728
+ finished_at: null,
729
+ task_id: null,
730
+ phase: "execution",
731
+ parent_run_id: null,
732
+ status: null,
733
+ duration_ms: null,
734
+ total_tokens: null,
735
+ cost: null,
736
+ currency: null,
737
+ events: null,
738
+ },
739
+ ],
740
+ canonical_daily_duration_ms: { "2026-08-02": 101_000 },
741
+ };
742
+ const operations = {
743
+ filters: { from: null, to: null },
744
+ summary: { task_count: 0 },
745
+ prds: [],
746
+ specs: [],
747
+ } as unknown as OperationsProjection;
748
+ const projection = buildCostSummaryProjection(summary, operations, "BRL", null);
749
+ const cutoffDay = projection.groups.daily.find((row) => row.key === "2026-08-02")!;
750
+ const unknownDay = projection.groups.daily.find((row) => row.key === "2026-08-03")!;
751
+
752
+ expect(cutoffDay).toMatchObject({
753
+ run_count: 2,
754
+ duration: {
755
+ known_sum: 101_000,
756
+ unknown: 0,
757
+ coverage_ratio: 1,
758
+ },
759
+ coverage_counts: {
760
+ metrics: { duration: { eligible_runs: 2, known_runs: 2, unknown_runs: 0 } },
761
+ },
762
+ });
763
+ expect(projection.groups.daily.reduce((total, row) => total + row.duration.known_sum, 0)).toBe(
764
+ 101_000,
765
+ );
766
+ expect(unknownDay.duration).toMatchObject({
767
+ known_sum: 0,
768
+ unknown: 0,
769
+ complete: true,
770
+ coverage_ratio: 1,
771
+ });
772
+ expect(projection.groups.monthly.find((row) => row.key === "2026-08")?.duration).toMatchObject({
773
+ unknown: 0,
774
+ complete: true,
775
+ coverage_ratio: 1,
776
+ });
777
+ expect(
778
+ projection.groups.monthly.find((row) => row.key === "2026-08")?.coverage_counts?.metrics
779
+ ?.duration,
780
+ ).toEqual({
781
+ eligible_runs: 2,
782
+ known_runs: 2,
783
+ unknown_runs: 0,
784
+ });
785
+ expect(projection.overview.average_run_duration_ms).toBe(2_000);
786
+ expect(projection.legacy_effort_baseline).toBeNull();
787
+
788
+ const filtered = buildCostSummaryProjection(
789
+ summary,
790
+ { ...operations, filters: { from: "2026-08-03", to: "2026-08-03" } },
791
+ "BRL",
792
+ null,
793
+ );
794
+ expect(filtered.legacy_effort_baseline).toBeNull();
795
+ expect(filtered.groups.daily).toHaveLength(1);
796
+ });
797
+
798
+ it("preserves each canonical SQLite day instead of redistributing duration by tokens", () => {
799
+ const period = (tokens: number) => ({
800
+ prds: 0,
801
+ specs: 0,
802
+ tasks: 0,
803
+ validations: 0,
804
+ evidences: 0,
805
+ runs: 1,
806
+ usage: {
807
+ total_tokens: { known_sum: tokens, unknown: 0, complete: true, coverage_ratio: 1 },
808
+ cost: { known_sum: 1, unknown: 0, complete: true, coverage_ratio: 1, currency: "BRL" as const },
809
+ },
810
+ });
811
+ const summary: CostSummarySource = {
812
+ periods: {
813
+ daily: {
814
+ "2026-08-01": period(1_000),
815
+ "2026-08-02": period(9_000),
816
+ },
817
+ },
818
+ canonical_daily_duration_ms: {
819
+ "2026-08-01": 9_000,
820
+ "2026-08-02": 1_000,
821
+ },
822
+ };
823
+ const operations = {
824
+ filters: { from: null, to: null },
825
+ summary: { task_count: 0 },
826
+ prds: [],
827
+ specs: [],
828
+ } as unknown as OperationsProjection;
829
+
830
+ const daily = buildCostSummaryProjection(summary, operations, "BRL", null).groups.daily;
831
+
832
+ expect(daily.find((row) => row.key === "2026-08-01")?.duration.known_sum).toBe(9_000);
833
+ expect(daily.find((row) => row.key === "2026-08-02")?.duration.known_sum).toBe(1_000);
834
+ });
835
+
836
+ it("uses São Paulo timestamp bounds for Cost daily labels and preserves the interval total", () => {
837
+ const period = () => ({
838
+ prds: 0,
839
+ specs: 0,
840
+ tasks: 0,
841
+ validations: 0,
842
+ evidences: 0,
843
+ runs: 0,
844
+ usage: {
845
+ total_tokens: { known_sum: 0, unknown: 0, complete: true, coverage_ratio: 1 },
846
+ cost: { known_sum: 0, unknown: 0, complete: true, coverage_ratio: 1, currency: "BRL" },
847
+ },
848
+ });
849
+ const summary: CostSummarySource = {
850
+ periods: {
851
+ daily: Object.fromEntries(
852
+ [
853
+ "2026-08-02",
854
+ "2026-08-03",
855
+ "2026-08-04",
856
+ "2026-08-05",
857
+ "2026-08-06",
858
+ "2026-08-07",
859
+ "2026-08-08",
860
+ ].map((day) => [day, period()]),
861
+ ),
862
+ },
863
+ run_metrics: [
864
+ {
865
+ id: "LEFT",
866
+ started_at: "2026-08-07T12:00:00.000Z",
867
+ finished_at: null,
868
+ task_id: null,
869
+ phase: "execution",
870
+ parent_run_id: null,
871
+ status: null,
872
+ duration_ms: 3_600_000,
873
+ total_tokens: null,
874
+ cost: null,
875
+ currency: null,
876
+ events: null,
877
+ },
878
+ {
879
+ id: "RIGHT",
880
+ started_at: "2026-08-07T12:30:00.000Z",
881
+ finished_at: null,
882
+ task_id: null,
883
+ phase: "execution",
884
+ parent_run_id: null,
885
+ status: null,
886
+ duration_ms: 3_600_000,
887
+ total_tokens: null,
888
+ cost: null,
889
+ currency: null,
890
+ events: null,
891
+ },
892
+ ],
893
+ };
894
+ const operations = {
895
+ filters: { from: "2026-08-02T03:00:00.000Z", to: "2026-08-08T02:59:59.999Z" },
896
+ summary: { task_count: 0 },
897
+ prds: [],
898
+ specs: [],
899
+ } as unknown as OperationsProjection;
900
+ summary.periods.daily["2026-08-07"] = {
901
+ ...period(),
902
+ duration: { known_sum: 5_400_000, unknown: 0, complete: true, coverage_ratio: 1 },
903
+ };
904
+ const daily = buildCostSummaryProjection(summary, operations, "BRL", null).groups.daily;
905
+
906
+ expect(daily.map((row) => row.key)).not.toContain("2026-08-08");
907
+ expect(daily.map((row) => row.key)).toEqual(
908
+ expect.arrayContaining(["2026-08-02", "2026-08-07"]),
909
+ );
910
+ expect(daily.reduce((total, row) => total + row.duration.known_sum, 0)).toBe(5_400_000);
911
+ });
912
+ it("keeps factual duration visible while retaining partial financial coverage", () => {
913
+ const known = (known_sum: number) => ({ known_sum, unknown: 0, complete: true, coverage_ratio: 1 });
914
+ const period = {
915
+ prds: 0, specs: 0, tasks: 0, validations: 0, evidences: 0, runs: 2,
916
+ usage: { total_tokens: known(100), cost: { ...known(10), currency: "BRL" } },
917
+ };
918
+ const operations = {
919
+ filters: { from: null, to: null }, summary: { task_count: 0 }, prds: [], specs: [],
920
+ } as unknown as OperationsProjection;
921
+ const partial = buildCostSummaryProjection({
922
+ periods: { daily: { "2026-08-12": period } },
923
+ cost_monitor_daily_duration: {
924
+ "2026-08-12": { known_sum: 60_000, eligible_runs: 2, known_runs: 1 },
925
+ },
926
+ }, operations, "BRL", null).groups.daily[0]!;
927
+ expect(partial).toMatchObject({ total_tokens: 100, estimated_brl: 10, duration_ms: 60_000 });
928
+ expect(partial.duration).toMatchObject({ known_sum: 60_000, unknown: 1, complete: false });
929
+
930
+ const observedZero = buildCostSummaryProjection({
931
+ periods: { daily: { "2026-08-12": { ...period, runs: 1 } } },
932
+ cost_monitor_daily_duration: {
933
+ "2026-08-12": { known_sum: 0, eligible_runs: 1, known_runs: 1 },
934
+ },
935
+ }, operations, "BRL", null).groups.daily[0]!;
936
+ expect(observedZero.duration_ms).toBe(0);
937
+ });
938
+ it("keeps monthly and annual duration unavailable when any financial day is incomplete", () => {
939
+ const known = (known_sum: number) => ({ known_sum, unknown: 0, complete: true, coverage_ratio: 1 });
940
+ const period = (tokens: number) => ({
941
+ prds: 0, specs: 0, tasks: 0, validations: 0, evidences: 0, runs: 1,
942
+ usage: { total_tokens: known(tokens), cost: { ...known(tokens), currency: "BRL" as const } },
943
+ });
944
+ const operations = { filters: { from: null, to: null }, summary: { task_count: 0 }, prds: [], specs: [] } as unknown as OperationsProjection;
945
+ const groups = buildCostSummaryProjection({
946
+ periods: { daily: { "2026-07-23": period(10), "2026-07-24": period(20) } },
947
+ cost_monitor_daily_duration: {
948
+ "2026-07-23": { known_sum: 20_000, eligible_runs: 1, known_runs: 1 },
949
+ "2026-07-24": { known_sum: 0, eligible_runs: 1, known_runs: 0 },
950
+ },
951
+ }, operations, "BRL", null).groups;
952
+ expect(groups.daily.map((row) => row.duration_ms)).toEqual([20_000, null]);
953
+ expect(groups.monthly[0]?.duration_ms).toBeNull();
954
+ expect(groups.annual[0]?.duration_ms).toBeNull();
955
+ });
956
+ });